Created
December 17, 2014 09:06
-
-
Save ghugues/639f459e189643b54041 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import <Foundation/Foundation.h> | |
@interface AppDownloadQueueOperation : NSOperation | |
- (instancetype)initWithURLSessionDataTask:(NSURLSessionDataTask *)dataTask; | |
@property (nonatomic, strong, readonly) NSURLSessionDataTask *dataTask; | |
@end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import "AppDownloadQueueOperation.h" | |
static void *AppDownloadQueueOperationTaskStateChangedContext = &AppDownloadQueueOperationTaskStateChangedContext; | |
@interface AppDownloadQueueOperation () { | |
BOOL _executing; | |
BOOL _finished; | |
} | |
@property (nonatomic) BOOL isObservingTaskState; | |
@end | |
@implementation AppDownloadQueueOperation | |
- (instancetype)initWithURLSessionDataTask:(NSURLSessionDataTask *)dataTask | |
{ | |
self = [super init]; | |
if (self) { | |
_dataTask = dataTask; | |
} | |
return self; | |
} | |
- (BOOL)isConcurrent { | |
return YES; | |
} | |
- (BOOL)isExecuting { | |
return _executing; | |
} | |
- (BOOL)isFinished { | |
return _finished; | |
} | |
- (void)start | |
{ | |
if ([self isCancelled]) { | |
[self willChangeValueForKey:@"isFinished"]; | |
_finished = YES; | |
[self didChangeValueForKey:@"isFinished"]; | |
return; | |
} | |
// If the operation is not canceled, begin executing the task. | |
[self willChangeValueForKey:@"isExecuting"]; | |
_executing = YES; | |
[self didChangeValueForKey:@"isExecuting"]; | |
[self.dataTask addObserver:self forKeyPath:@"state" options:NSKeyValueObservingOptionNew context:AppDownloadQueueOperationTaskStateChangedContext]; | |
self.isObservingTaskState = YES; | |
[self.dataTask resume]; | |
} | |
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context | |
{ | |
if (context == AppDownloadQueueOperationTaskStateChangedContext && object == self.dataTask && [keyPath isEqualToString:@"state"]) | |
{ | |
NSNumber *newStateValue = change[NSKeyValueChangeNewKey]; | |
NSURLSessionTaskState newState = newStateValue.integerValue; | |
if (newState == NSURLSessionTaskStateCompleted) { | |
[self completeOperation]; | |
} | |
} | |
else { | |
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; | |
} | |
} | |
- (void)completeOperation | |
{ | |
@synchronized(self) { | |
if (_finished == NO || _executing == YES) { | |
[self willChangeValueForKey:@"isFinished"]; | |
[self willChangeValueForKey:@"isExecuting"]; | |
_executing = NO; | |
_finished = YES; | |
[self didChangeValueForKey:@"isExecuting"]; | |
[self didChangeValueForKey:@"isFinished"]; | |
} | |
} | |
} | |
- (void)dealloc | |
{ | |
if (self.isObservingTaskState) { | |
[self.dataTask removeObserver:self forKeyPath:@"state" context:AppDownloadQueueOperationTaskStateChangedContext]; | |
} | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment