cocoa - NSOperation wait until asynchronous block executes -
i need put asynchronous operations operation queue, however, need execute on after other
self.operationqueue = [nsoperationqueue new]; self.operationqueue.maxconcurrentoperationcount = 1; [self.operationqueue addoperationwithblock:^{ // asynchronous [peripheral1 connectwithcompletion:^(nserror *error) { }]; }]; [self.operationqueue addoperationwithblock:^{ // asynchronous [peripheral2 connectwithcompletion:^(nserror *error) { }]; }];
the problem is, since peripheraln connectwithcompletion asynchronous, operation in queue ended , next executed, need simulate, peripheraln connectwithcompletion synchronous , wait end of operation, till asynchronous block executes
so need behaviour this, using operation queue
[peripheral1 connectwithcompletion:^(nserror *error) { [peripheral2 connectwithcompletion:^(nserror *error) { }]; }];
nsblockoperation
can't handle asynchronous operations, it's not hard create subclass of nsoperation
can...
basically, need create nsoperation
takes block takes another block completion handler. block defined this:
typedef void(^asyncblock)(dispatch_block_t completionhandler);
then, in nsoperation
subclass's start
method, need call asyncblock
passing dispatch_block_t
called when it's done executing. need sure stay kvo
compliant nsoperation
's isfinished
, isexecuting
properties (at minimum) (see kvo-compliant properties in nsoperation
docs); allows nsoperationqueue
wait until asynchronous operation complete.
something this:
- (void)start { [self willchangevalueforkey:@"isexecuting"]; _executing = yes; [self didchangevalueforkey:@"isexecuting"]; self.block(^{ [self willchangevalueforkey:@"isexecuting"]; _executing = no; [self didchangevalueforkey:@"isexecuting"]; [self willchangevalueforkey:@"isfinished"]; _finished = yes; [self didchangevalueforkey:@"isfinished"]; }); }
note _executing
, _finished
need defined in subclass somewhere, , you'll need override isexecuting
, isfinished
properties return correct values.
if put together, along initializer takes asyncblock
, can add operations queue this:
[self.operationqueue addoperationwithblock:^(dispatch_block_t completionhandler) { [peripheral1 connectwithcompletion:^(nserror *error) { // call completionhandler when operation done completionhandler(); }]; }]; [self.operationqueue addoperationwithblock:^(dispatch_block_t completionhandler) { [peripheral2 connectwithcompletion:^(nserror *error) { // call completionhandler when operation done completionhandler(); }]; }];
i put gist of simple version of here: asyncoperationblock. it's minimum implementation, should work (it nice if iscancelled
implemented, example).
copied here completeness:
asyncblockoperation.h:
#import <foundation/foundation.h> typedef void(^asyncblock)(dispatch_block_t completionhandler); @interface asyncblockoperation : nsoperation @property (nonatomic, readonly, copy) asyncblock block; + (instancetype)asyncblockoperationwithblock:(asyncblock)block; - (instancetype)initwithasyncblock:(asyncblock)block; @end @interface nsoperationqueue (asyncblockoperation) - (void)addasyncoperationwithblock:(asyncblock)block; @end
asyncblockoperation.m:
#import "asyncblockoperation.h" @interface asyncblockoperation () { bool _finished; bool _executing; } @property (nonatomic, copy) asyncblock block; @end @implementation asyncblockoperation + (instancetype)asyncblockoperationwithblock:(asyncblock)block { return [[asyncblockoperation alloc] initwithasyncblock:block]; } - (instancetype)initwithasyncblock:(asyncblock)block { if (self = [super init]) { self.block = block; } return self; } - (void)start { [self willchangevalueforkey:@"isexecuting"]; _executing = yes; [self didchangevalueforkey:@"isexecuting"]; self.block(^{ [self willchangevalueforkey:@"isexecuting"]; _executing = no; [self didchangevalueforkey:@"isexecuting"]; [self willchangevalueforkey:@"isfinished"]; _finished = yes; [self didchangevalueforkey:@"isfinished"]; }); } - (bool)isfinished { return _finished; } - (bool)isexecuting { return _executing; } - (bool)isasynchronous { return yes; } @end @implementation nsoperationqueue (asyncblockoperation) - (void)addasyncoperationwithblock:(asyncblock)block { [self addoperation:[asyncblockoperation asyncblockoperationwithblock:block]]; } @end
Comments
Post a Comment