Search code examples
objective-cuiviewcontrollerautomatic-ref-countingmodal-dialogpushviewcontroller

Difference between presentModalViewController and pushViewController regarding memory management


Although I've solved this problem. I really need someone to explain to me why it worked.

I've got a UINavBar that has a custom UIView as the visible ViewController. I created a custom button in place of the navbar's title view and set it as autorelease (I'm customising existing non-ARC code):

- (void)loadView {
    ..  

    UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [button addTarget:self
               action:@selector(presentEmailThreadList)
     forControlEvents:UIControlEventTouchDown];
    [button setTitle:[NSString stringWithFormat:@"1 of %d",self.numThreads] forState:UIControlStateNormal];
    button.frame = CGRectMake(80.0, 210.0, 160.0, 40.0);

    self.navigationItem.titleView = [button autorelease];
}

This code works when I present a view modally ie:

[self presentModalViewController:emailThreadListVC animated:YES];

but gives me an EXC_BAD_ACCESS error if I try to push it to the navigation stack, then click the 'back button' on the new VC:

[self.navigationController pushViewController:emailThreadListVC animated:YES];

and specifically crashes at the UINavigationItemTitleView:

enter image description here

I've concluded that the titleView no longer exists when I try to go back to the original VC, meaning that the autorelease did decrement the reference count on the titleView when I push a VC ontop the stack, but it won't decrement the reference count when I push a VC modally.

Any idea why?


Solution

  • The problem is here:

    UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    ...
    self.navigationItem.titleView = [button autorelease];  <-- DOUBLE AUTORELEASE
    

    buttonWithType already returns an autoreleased object, so you do not need to explicitly autorelease it again.

    Why it works when you use presentViewController is another issue. I think it comes down to different timings in the two cases.