3

I'm trying to get my head around how object lifetime and reference counting interact with code blocks. In the following code I'm just doing a simple animation that flashes as the top view on a UINavigationController's stack is swapped. The tricky part is that the popped view controller is the one where this code is defined.

[UIView animateWithDuration:0.2 
        animations:^{self.navigationController.view.alpha = 0.0;}
        completion:^(BOOL finished){ 
                UINavigationController *navController = self.navigationController;  

                [self.navigationController popViewControllerAnimated:NO]; 
                [navController pushViewController:nextView animated:NO];
                [nextView release];

                [UIView animateWithDuration:0.2 
                        animations:^{navController.view.alpha = 1.0;}];                    
                 }];    

My question is (ignoring what the animation looks like), is this the correct way to do this from a memory management perspective. In particular:

(1) When using this approach for the pop+push cycle, is it correct that it is no longer necessary to retain self, as in other similar examples that do not use blocks?

(2) Does invoking animateWithDuration:... with the these blocks retain the defining view controller (self) until the blocks execute?

Community
  • 1
  • 1
orome
  • 45,163
  • 57
  • 202
  • 418

1 Answers1

5

(1) When using this approach the the pop+push cycle, is it correct that it is no longer necessary to retain self, as in other similar examples that do not use blocks?

It is correct. These blocks automatically retain self, navController and nextView if nextView is local variable.

(2) Does invoking animateWithDuration:... with the these blocks retain the defining view controller (self) until the blocks execute?

These blocks are copied to heap from stack by this method. And these blocks are released after execution. And then self, navController and nextView are released from these blocks.

Kazuki Sakamoto
  • 13,929
  • 2
  • 34
  • 96
  • So 'self' and the navController are retained because they are actively referenced from inside the block correct? If however, the above code did not have the line "navController = self.navigationController", but instead had "navController = mNavigationController" - where mNavigationController is an ivar, then mNavigationController would have been retained, but not 'self'. Right? I just want to confirm whether or not blocks automagically retain their 'host' instances, namely 'self'. – Dev Kanchen Jun 21 '11 at 13:46
  • 1
    "self.navigationController" is same as "[self navigationController]", and "mNavigationController" is same as "self->mNavigationController", thus self is retained in both cases. If you want to avoid retaining self, use local variable as "UINavigationController *controller = self.navigationController;", and then use "controller" in blocks. – Kazuki Sakamoto Jun 21 '11 at 21:05
  • Comment redacted: I got it now! Thanks. – Dev Kanchen Jun 22 '11 at 05:25
  • I did `ATSDragToReorderTableViewController *blockSelf = self;` and used the local blockSelf, but somehow self is still retained and not released (dealloc of self not being called when I pop it). What did I do wrong??? – Hlung Jul 20 '12 at 08:36
  • hmm, I recommend you to create a question with your code snippet. – Kazuki Sakamoto Jul 20 '12 at 09:26