Skip to content

Instantly share code, notes, and snippets.

@churchofthought
Created April 30, 2013 02:58
Show Gist options
  • Save churchofthought/5486357 to your computer and use it in GitHub Desktop.
Save churchofthought/5486357 to your computer and use it in GitHub Desktop.
//
// AsyncBlockOperation.h
//
// Created by XibXor.com on 4/29/13.
//
//
#import <Foundation/Foundation.h>
@class AsyncBlockOperation;
typedef void (^td_async_block_operation_opblock)(AsyncBlockOperation* op);
@interface AsyncBlockOperation : NSOperation
@property (atomic, assign) BOOL isExecuting;
@property (atomic, assign) BOOL isFinished;
@property (atomic, strong) td_async_block_operation_opblock executionBlock;
+ (id) blockOperationWithBlock:(td_async_block_operation_opblock) block;
- (id) initWithBlock:(td_async_block_operation_opblock) block;
- (void) complete;
@end
//
// AsyncBlockOperation.m
//
// Created by XibXor.com on 4/29/13.
//
//
#import "AsyncBlockOperation.h"
@interface AsyncBlockOperation()
@end
@implementation AsyncBlockOperation
+ (id) blockOperationWithBlock:(td_async_block_operation_opblock) block {
return [[self alloc] initWithBlock:block];
}
- (id) initWithBlock:(td_async_block_operation_opblock) block {
self = [self init];
_executionBlock = block;
return self;
}
- (void) start {
if (_executionBlock){
// set status properties and fire off KVO
[self setIsRunning:YES];
// execute the block, passing self for completion
_executionBlock(self);
// release the execution block after execution
_executionBlock = nil;
}else {
[self complete];
}
}
- (void) complete {
// release the execution block
_executionBlock = nil;
// set status properties and fire off KVO
[self setIsRunning:NO];
}
- (void) setIsRunning: (BOOL) isRunning {
[self willChangeValueForKey:@"isExecuting"];
[self willChangeValueForKey:@"isFinished"];
self.isFinished = !(self.isExecuting = isRunning);
[self didChangeValueForKey:@"isExecuting"];
[self didChangeValueForKey:@"isFinished"];
}
@end
AsyncBlockOperation is very similar to NSBlockOperation with one caveat; the block you pass to it receives one argument, a reference to the AsyncBlockOperation for the block. When your block is done with its task, it must call [op complete]
Example usage:
NSOperation* asyncOp = [AsyncBlockOperation blockOperationWithBlock:^(AsyncBlockOperation* op) {
NSLog(@"starting op");
double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
if (op.isCancelled){
return [op complete];
}
NSLog(@"2 seconds have passed");
NSLog(@"calling [op complete]");
[op complete];
});
NSLog(@"op block returns but op isn't finished");
}];
asyncOp.completionBlock = ^{
NSLog(@"completion block called!");
};
[asyncOp start];
Output in terminal will be:
2013-04-29 22:51:57.417 Experiments[5795:11603] starting op
2013-04-29 22:51:57.419 Experiments[5795:11603] op block returns but op isn't finished
2013-04-29 22:51:59.420 Experiments[5795:11603] 2 seconds have passed
2013-04-29 22:51:59.421 Experiments[5795:11603] calling [op complete]
2013-04-29 22:51:59.422 Experiments[5795:12e03] completion block called!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment