I'm a big fan of blocks, but have not used them for concurrency. After some googling, I pieced together this idea to hide everything I learned in one place. The goal is to execute a block in the background, and when it's finished, execute another block (like UIView animation)...
- (NSOperation *)executeBlock:(void (^)(void))block completion:(void (^)(BOOL finished))completion {
NSOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:block];
NSOperation *completionOperation = [NSBlockOperation blockOperationWithBlock:^{
completion(blockOperation.isFinished);
}];
[completionOperation addDependency:blockOperation];
[[NSOperationQueue mainQueue] addOperation:completionOperation];
NSOperationQueue *backgroundOperationQueue = [[NSOperationQueue alloc] init];
[backgroundOperationQueue addOperation:blockOperation];
return blockOperation;
}
- (void)testIt {
NSMutableString *string = [NSMutableString stringWithString:@"tea"];
NSString *otherString = @"for";
NSOperation *operation = [self executeBlock:^{
NSString *yetAnother = @"two";
[string appendFormat:@" %@ %@", otherString, yetAnother];
} completion:^(BOOL finished) {
// this logs "tea for two"
NSLog(@"%@", string);
}];
NSLog(@"keep this operation so we can cancel it: %@", operation);
}
My questions are:
- It works when I run it, but am I missing anything ... hidden land mine? I haven't tested cancellation (because I haven't invented a long operation), but does that look like it will work?
- I'm concerned that I need to qualify my declaration of backgroundOperation so that I can refer to it in the completion block. The compiler doesn't complain, but is there a retain cycle lurking there?
- If the "string" were an ivar, what would happen if I key-value observed it while the block was running? Or setup a timer on the main thread and periodically logged it? Would I be able to see progress? Would I declare it atomic?
- If this works as I expect, then it seems like a good way to hide all the details and get concurrency. Why didn't Apple write this for me? Am I missing something important?
Thanks.