My block is not retaining some of its objects

Posted by Drew Crawford on Stack Overflow See other posts from Stack Overflow or by Drew Crawford
Published on 2011-01-03T20:14:03Z Indexed on 2011/01/03 20:54 UTC
Read the original article Hit count: 495

From the Blocks documentation:

In a reference-counted environment, by default when you reference an Objective-C object within a block, it is retained. This is true even if you simply reference an instance variable of the object.

I am trying to implement a completion handler pattern, where a block is given to an object before the work is performed and the block is executed by the receiver after the work is performed. Since I am being a good memory citizen, the block should own the objects it references in the completion handler and then they will be released when the block goes out of scope. I know enough to know that I must copy the block to move it to the heap since the block will survive the stack scope in which it was declared.

However, one of my objects is getting deallocated unexpectedly. After some playing around, it appears that certain objects are not retained when the block is copied to the heap, while other objects are. I am not sure what I am doing wrong. Here's the smallest test case I can produce:

typedef void (^ActionBlock)(UIView*);

In the scope of some method:

NSObject *o = [[[NSObject alloc] init] autorelease];
        mailViewController = [[[MFMailComposeViewController alloc] init] autorelease];
        NSLog(@"o's retain count is %d",[o retainCount]);
        NSLog(@"mailViewController's retain count is %d",[mailViewController retainCount]);
        ActionBlock myBlock = ^(UIView *view) {
            [mailViewController setCcRecipients:[NSArray arrayWithObjects:@"[email protected]",nil]];
            [o class];
    };
        NSLog(@"mailViewController's retain count after the block is %d",[mailViewController retainCount]);
        NSLog(@"o's retain count after the block is %d",[o retainCount]);
        Block_copy(myBlock);
        NSLog(@"o's retain count after the copy is %d",[o retainCount]);
        NSLog(@"mailViewController's retain count after the copy is %d",[mailViewController retainCount]);

I expect both objects to be retained by the block at some point, and I certainly expect their retain counts to be identical. Instead, I get this output:

o's retain count is 1
mailViewController's retain count is 1
mailViewController's retain count after the block is 1
o's retain count after the block is 1
o's retain count after the copy is 2
mailViewController's retain count after the copy is 1

o (subclass of NSObject) is getting retained properly and will not go out of scope. However mailViewController is not retained and will be deallocated before the block is run, causing a crash.

© Stack Overflow or respective owner

Related posts about iphone

Related posts about objective-c