From 2ec0c3ec2faa7642332b44cd00c6a6ccf0ca0d59 Mon Sep 17 00:00:00 2001 From: Mattt Thompson Date: Tue, 20 Mar 2012 11:31:18 -0700 Subject: [PATCH] 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; }