Skip to content

Instantly share code, notes, and snippets.

@ghugues
Created December 17, 2014 09:06
Show Gist options
  • Save ghugues/639f459e189643b54041 to your computer and use it in GitHub Desktop.
Save ghugues/639f459e189643b54041 to your computer and use it in GitHub Desktop.
#import <Foundation/Foundation.h>
@interface AppDownloadQueueOperation : NSOperation
- (instancetype)initWithURLSessionDataTask:(NSURLSessionDataTask *)dataTask;
@property (nonatomic, strong, readonly) NSURLSessionDataTask *dataTask;
@end
#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