From 2ec0c3ec2faa7642332b44cd00c6a6ccf0ca0d59 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Tue, 20 Mar 2012 11:31:18 -0700 Subject: [PATCH 1/4] Adding AFURLConnectionOperation -setShouldExecuteAsBackgroundTaskWithExpirationHandler: --- AFNetworking/AFURLConnectionOperation.h | 13 +++++++++ AFNetworking/AFURLConnectionOperation.m | 35 +++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/AFNetworking/AFURLConnectionOperation.h b/AFNetworking/AFURLConnectionOperation.h index 14d0226..c9294d3 100644 --- a/AFNetworking/AFURLConnectionOperation.h +++ b/AFNetworking/AFURLConnectionOperation.h @@ -169,6 +169,19 @@ extern NSString * const AFNetworkingOperationDidFinishNotification; */ - (id)initWithRequest:(NSURLRequest *)urlRequest; +///---------------------------------------------- +/// @name Configuring Backgrounding Task Behavior +///---------------------------------------------- + +/** + Specifies that the operation should continue execution after the app has entered the background, and the expiration handler for that background task. + + @param handler A handler to be called shortly before the application’s remaining background time reaches 0. The handler is wrapped in a block that cancels the operation, and cleans up and marks the end of execution, unlike the `handler` parameter in `UIApplication -beginBackgroundTaskWithExpirationHandler:`, which expects this to be done in the handler itself. The handler is called synchronously on the main thread, thus blocking the application’s suspension momentarily while the application is notified. + */ +#if __IPHONE_OS_VERSION_MIN_REQUIRED +- (void)setShouldExecuteAsBackgroundTaskWithExpirationHandler:(void (^)(void))handler; +#endif + ///--------------------------------- /// @name Setting Progress Callbacks ///--------------------------------- diff --git a/AFNetworking/AFURLConnectionOperation.m b/AFNetworking/AFURLConnectionOperation.m index 172595a..8c64c91 100644 --- a/AFNetworking/AFURLConnectionOperation.m +++ b/AFNetworking/AFURLConnectionOperation.m @@ -30,6 +30,12 @@ typedef enum { typedef unsigned short AFOperationState; +#if __IPHONE_OS_VERSION_MIN_REQUIRED +typedef UIBackgroundTaskIdentifier AFBackgroundTaskIdentifier; +#else +typedef id AFBackgroundTaskIdentifier; +#endif + static NSUInteger const kAFHTTPMinimumInitialDataCapacity = 1024; static NSUInteger const kAFHTTPMaximumInitialDataCapacity = 1024 * 1024 * 8; @@ -94,6 +100,7 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat @property (readwrite, nonatomic, copy) NSString *responseString; @property (readwrite, nonatomic, assign) NSInteger totalBytesRead; @property (readwrite, nonatomic, retain) NSMutableData *dataAccumulator; +@property (readwrite, nonatomic, assign) AFBackgroundTaskIdentifier backgroundTaskIdentifier; @property (readwrite, nonatomic, copy) AFURLConnectionOperationProgressBlock uploadProgress; @property (readwrite, nonatomic, copy) AFURLConnectionOperationProgressBlock downloadProgress; @property (readwrite, nonatomic, copy) AFURLConnectionOperationAuthenticationAgainstProtectionSpaceBlock authenticationAgainstProtectionSpace; @@ -117,6 +124,7 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat @synthesize dataAccumulator = _dataAccumulator; @dynamic inputStream; @synthesize outputStream = _outputStream; +@synthesize backgroundTaskIdentifier = _backgroundTaskIdentifier; @synthesize uploadProgress = _uploadProgress; @synthesize downloadProgress = _downloadProgress; @synthesize authenticationAgainstProtectionSpace = _authenticationAgainstProtectionSpace; @@ -189,6 +197,13 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat [_outputStream release]; _outputStream = nil; } + +#if __IPHONE_OS_VERSION_MIN_REQUIRED + if (_backgroundTaskIdentifier) { + [[UIApplication sharedApplication] endBackgroundTask:_backgroundTaskIdentifier]; + _backgroundTaskIdentifier = UIBackgroundTaskInvalid; + } +#endif [_uploadProgress release]; [_downloadProgress release]; @@ -229,6 +244,26 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat self.request = mutableRequest; } +#if __IPHONE_OS_VERSION_MIN_REQUIRED +- (void)setShouldExecuteAsBackgroundTaskWithExpirationHandler:(void (^)(void))handler { + [self.lock lock]; + if (!self.backgroundTaskIdentifier) { + UIApplication *application = [UIApplication sharedApplication]; + self.backgroundTaskIdentifier = [application beginBackgroundTaskWithExpirationHandler:^{ + if (handler) { + handler(); + } + + [self cancel]; + + [application endBackgroundTask:self.backgroundTaskIdentifier]; + self.backgroundTaskIdentifier = UIBackgroundTaskInvalid; + }]; + } + [self.lock unlock]; +} +#endif + - (void)setUploadProgressBlock:(void (^)(NSInteger bytesWritten, NSInteger totalBytesWritten, NSInteger totalBytesExpectedToWrite))block { self.uploadProgress = block; } From 2868b069cdd9807fc45c0eba6ffaee4479dca391 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Tue, 20 Mar 2012 11:32:44 -0700 Subject: [PATCH 2/4] Adding missing extern specifier for AFQueryStringComponentFromKeyAndValueWithEncoding(...) --- AFNetworking/AFHTTPClient.m | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/AFNetworking/AFHTTPClient.m b/AFNetworking/AFHTTPClient.m index f0f07e0..adfe032 100644 --- a/AFNetworking/AFHTTPClient.m +++ b/AFNetworking/AFHTTPClient.m @@ -154,6 +154,7 @@ NSString * AFURLEncodedStringFromStringWithEncoding(NSString *string, NSStringEn #pragma mark - +extern AFQueryStringComponent * AFQueryStringComponentFromKeyAndValueWithEncoding(id key, id value, NSStringEncoding stringEncoding); extern NSArray * AFQueryStringComponentsFromKeyAndValueWithEncoding(NSString *key, id value, NSStringEncoding stringEncoding); extern NSArray * AFQueryStringComponentsFromKeyAndDictionaryValueWithEncoding(NSString *key, NSDictionary *value, NSStringEncoding stringEncoding); extern NSArray * AFQueryStringComponentsFromKeyAndArrayValueWithEncoding(NSString *key, NSArray *value, NSStringEncoding stringEncoding); @@ -465,9 +466,9 @@ static void AFReachabilityCallback(SCNetworkReachabilityRef __unused target, SCN if (!operation) { operation = [[[AFHTTPRequestOperation alloc] initWithRequest:urlRequest] autorelease]; } - + [operation setCompletionBlockWithSuccess:success failure:failure]; - + return operation; } From e61275110b4f17726d4468b5deef3a393a8d7c82 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Tue, 20 Mar 2012 11:33:15 -0700 Subject: [PATCH 3/4] Adding locking to AFURLConnectionOperation -setInputStream: --- AFNetworking/AFURLConnectionOperation.m | 2 ++ 1 file changed, 2 insertions(+) diff --git a/AFNetworking/AFURLConnectionOperation.m b/AFNetworking/AFURLConnectionOperation.m index 8c64c91..a370e0c 100644 --- a/AFNetworking/AFURLConnectionOperation.m +++ b/AFNetworking/AFURLConnectionOperation.m @@ -239,9 +239,11 @@ static inline BOOL AFStateTransitionIsValid(AFOperationState fromState, AFOperat } - (void)setInputStream:(NSInputStream *)inputStream { + [self.lock lock]; NSMutableURLRequest *mutableRequest = [[self.request mutableCopy] autorelease]; mutableRequest.HTTPBodyStream = inputStream; self.request = mutableRequest; + [self.lock unlock]; } #if __IPHONE_OS_VERSION_MIN_REQUIRED From e4c84db10bb8e9c9b52f53f6b6f7cb42e2e005f5 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Sun, 8 Apr 2012 12:42:44 -0700 Subject: [PATCH 4/4] Removing stray newline --- AFNetworking/AFHTTPRequestOperation.m | 1 - 1 file changed, 1 deletion(-) diff --git a/AFNetworking/AFHTTPRequestOperation.m b/AFNetworking/AFHTTPRequestOperation.m index 5fbd11f..df3e7ce 100644 --- a/AFNetworking/AFHTTPRequestOperation.m +++ b/AFNetworking/AFHTTPRequestOperation.m @@ -57,7 +57,6 @@ static void AFSwizzleClassMethodWithClassAndSelectorUsingBlock(Class klass, SEL Method originalMethod = class_getClassMethod(klass, selector); IMP implementation = imp_implementationWithBlock(block); class_replaceMethod(objc_getMetaClass([NSStringFromClass(klass) UTF8String]), selector, implementation, method_getTypeEncoding(originalMethod)); - } static NSString * AFStringFromIndexSet(NSIndexSet *indexSet) {