Michael Melanson
Michael Melanson

Reputation: 1335

Must I copy a block here?

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

Answers (2)

joerick
joerick

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

user529758
user529758

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

Related Questions