Reputation: 303
Using Xcode 4.2 and ARC, I wrote the following code before I had any understanding of how blocks needed to be copied from the stack to the heap.
-(void) downloadWithBlock:(void (^)(void))callbackBlock;
{
// start the data download in the background...
NSOperation *backgroundOperation = [NSBlockOperation blockOperationWithBlock:^{
// synchronous download code
}];
[backgroundOperationQueue addOperation:backgroundOperation];
NSOperation *foregroundOperation = [NSBlockOperation blockOperationWithBlock:^{
callbackBlock();
}];
[foregroundOperation addDependency:backgroundOperation];
[[NSOperationQueue mainQueue] addOperation:foregroundOperation];
}
The code works, but I don't trust it because I don't understand it. In another section of code, I experienced application crashes while invoking blocks that were stored in ivars without using -copy. That has made me wonder whether this section of code should be rewritten like this:
-(void) downloadWithBlock:(void (^)(void))callbackBlock;
{
void(^heapBlock)(void) = [callbackBlock copy];
// start the data download in the background...
NSOperation *backgroundOperation = [NSBlockOperation blockOperationWithBlock:^{
// synchronous download code
}];
[backgroundOperationQueue addOperation:backgroundOperation];
NSOperation *foregroundOperation = [NSBlockOperation blockOperationWithBlock:^{
heapBlock();
}];
[foregroundOperation addDependency:backgroundOperation];
[[NSOperationQueue mainQueue] addOperation:foregroundOperation];
}
My only concern here is to gain a better understanding of how block pointers work. Is either of these code sections acceptable? Does the invocation of a block within another block trigger the compiler to insert a hidden Block_copy operation?
Upvotes: 4
Views: 367
Reputation: 4227
Not just the invocation of a block inside a block but any direct reference to one will cause a copy. Including passing it as an argument to something else. Same goes for ObjC types in the block (except it is a simple retain, not a copy for them).
Upvotes: 1