Ash Furrow
Ash Furrow

Reputation: 12421

__block self reference cycle in ivar block in ARC

I've got some code with an apparent reference cycle in a block ivar. The following code causes a reference cycle and dealloc is never called:

__block MyViewController *blockSelf = self;

loggedInCallback = ^(BOOL success, NSError *error){
    if (success)
    {
        double delayInSeconds = 1.0;
        dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
        dispatch_after(popTime, dispatch_get_main_queue(), ^(void)
        {
            [blockSelf.delegate loginDidFinish];
        });            
    }
};

However, if I create another __block variable to hold a reference to my delegate for the block's scope to capture, the reference cycle goes away:

__block id <MyViewControllerDelegate> blockDelegate = self.delegate;

loggedInCallback = ^(BOOL success, NSError *error){
    if (success)
    {
        double delayInSeconds = 1.0;
        dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
        dispatch_after(popTime, dispatch_get_main_queue(), ^(void)
        {
            [blockDelegate loginDidFinish];
        });            
    }
};

Just want to understand what's going on here.

Upvotes: 9

Views: 2793

Answers (1)

Joshua Weinberg
Joshua Weinberg

Reputation: 28688

I'm going to assume your'e using ARC here. Prior to ARC, your first example would work just fine. With ARC the semantics of __block have changed. __block declarations are now strongly captured, rather than weakly. Replace __block with __weak in your first sample and all should work as expected.

As for what the second example works, you are creating a strong reference to the delegate, but your that doesn't have a reference back to your object. Thus no cycle and everyone is happy.

I recommend reading Mike Ash's article on the changes introduced with ARC, especially around block capture and __weak http://www.mikeash.com/pyblog/friday-qa-2011-09-30-automatic-reference-counting.html

Upvotes: 16

Related Questions