Reputation: 1335
I understand that you must copy blocks in order for them to stick around after a stack frame exits. But, how does that apply to stack-allocated blocks used within a nested block as in the following code example:
- doSomethingFunkyThenCall:(void(^)(int someValue))callback
{
[[NSOperationQueue currentQueue] addOperationWithBlock:^{
// ... do some work here, potentially nesting into further blocks ...
callback(result);
}];
}
Obviously, the doSomethingFunkyThenCall:
stack frame will terminate before the callback is executed, so it will have to be copied. But will this happen automatically in the call to addOperationWithBlock:
or do I have to do it manually?
Upvotes: 6
Views: 617
Reputation: 16448
Yes, you should do a callback = [[callback copy] autorelease];
at the top of this method.
Objects used in blocks are retained automatically, but sending a stack-block retain actually does nothing (because the semantics of retain require it to return the receiver), so will be gone once we leave the frame it was created in.
Sources:
http://cocoawithlove.com/2009/10/how-blocks-are-implemented-and.html
http://thirdcog.eu/pwcblocks/#objcblocks
EDIT: It turns out I'm wrong. @bbum points out below that Block_copy will copy recursively, and since addOperationWithBlock:
copies it's block, the callback is also copied.
Upvotes: 0
Reputation:
Most likely, it will happen automatically. Cocoa's design principles imply in general that you're not responsible for objects (their memory management, passing blocks [which are, in fact, implemented as proper Objective-C objects], etc.) you haven't created. So you can just pass down the block you received as a parameter, and the runtime will manage it as per its needs.
Upvotes: 3