David Y.
David Y.

Reputation: 303

Blocks, Stacks, & Heaps

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

Answers (1)

Stripes
Stripes

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

Related Questions