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

Popular posts from this blog

c++ - QTextObjectInterface with Qml TextEdit (QQuickTextEdit) -

javascript - angular ng-required radio button not toggling required off in firefox 33, OK in chrome -

xcode - Swift Playground - Files are not readable -