关于内存管理的presentModalViewController和pushViewController之间的区别

时间:2013-01-14 10:17:10

标签: objective-c uiviewcontroller automatic-ref-counting modal-dialog pushviewcontroller

虽然我已经解决了这个问题。我真的需要有人向我解释它为何有效。

我有一个UINavBar,其自定义UIView作为可见的ViewController。我创建了一个自定义按钮来代替导航栏的标题视图,并将其设置为autorelease(我正在自定义现有的非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];
}

当我以模态方式呈现视图时,此代码有效:

[self presentModalViewController:emailThreadListVC animated:YES];

但如果我尝试将其推送到导航堆栈,然后点击新VC上的“后退按钮”,则会给我EXC_BAD_ACCESS错误:

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

并特别在UINavigationItemTitleView

崩溃

enter image description here

我得出的结论是,当我尝试回到原来的VC时,titleView不再存在,这意味着autorelease确实减少了titleView上的引用计数将VC推到堆栈上,但是当我按模式推送VC时,它不会减少引用计数。

知道为什么吗?

1 个答案:

答案 0 :(得分:1)

问题在于:

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

buttonWithType已经返回一个自动释放的对象,因此您无需再次显式自动释放它。

当您使用presentViewController时,它的工作原理是另一个问题。我认为这归结为两种情况下的不同时间。