Skip to content

Instantly share code, notes, and snippets.

@jpmhouston
Created September 6, 2014 04:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jpmhouston/e092cc33c36de8986631 to your computer and use it in GitHub Desktop.
Save jpmhouston/e092cc33c36de8986631 to your computer and use it in GitHub Desktop.
NSOperation subclass implementing +asyncOperationWithBlock:
#import <Foundation/Foundation.h>
@interface AsyncOperation : NSOperation
@property (nonatomic, assign) BOOL isExecuting; // yes, explicity not '.. getter=isExecuting) BOOL executing'
@property (nonatomic, assign) BOOL isFinished; // the KVC keys must be isExecuting & isFinished, with the 'is'
typedef void (^FinishBlock)(void);
+ (instancetype)asyncOperationWithBlock:(void (^)(FinishBlock finishBlock))block;
+ (instancetype)asyncOperationOnMainThreadWithBlock:(void (^)(FinishBlock finishBlock))block;
@end
#import "AsyncOperation.h"
@interface AsyncOperation ()
@property (nonatomic, strong) void (^operationBlock)(FinishBlock);
@property (nonatomic, assign) BOOL onMainThread;
@end
@implementation AsyncOperation
+ (instancetype)asyncOperationWithBlock:(void (^)(FinishBlock finishBlock))block
{
return [[self alloc] initWithBlock:block toRunOnMainThread:NO];
}
+ (instancetype)asyncOperationOnMainThreadWithBlock:(void (^)(FinishBlock finishBlock))block
{
AsyncOperation *obj = [[self alloc] initWithBlock:block toRunOnMainThread:YES];
return obj;
}
- (instancetype)initWithBlock:(void (^)(FinishBlock finishBlock))block toRunOnMainThread:(BOOL)mainThread
{
self = [super init];
if (self)
{
self.operationBlock = block;
self.onMainThread = mainThread;
}
return self;
}
- (void)start
{
if (self.isCancelled || self.operationBlock == nil)
{
self.isFinished = YES;
}
else
{
self.isExecuting = YES;
FinishBlock finishBlock = ^{
self.isExecuting = NO;
self.isFinished = YES;
};
if (self.onMainThread && ![NSThread isMainThread]) // necessary??
dispatch_async(dispatch_get_main_queue(), ^{ self.operationBlock(finishBlock); });
else
self.operationBlock(finishBlock);
}
}
- (BOOL)isConcurrent
{
return YES;
}
// this makes it so will/didChangeValueForKey isFinished automatically get called, like normal properties
+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key
{
if ([key isEqualToString:@"isExecuting"] || [key isEqualToString:@"isFinished"])
return YES;
return [super automaticallyNotifiesObserversForKey:key];
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment