为什么会出现过度释放?UINavigationController / UITableview

10

我正在使用如下代码将一个视图控制器推到导航控制器的堆栈中,该代码位于我的TableViewController的didSelectRowAtIndexPath方法中:

MyViewController *myViewController = [[MyViewController alloc] initWithNibName:@"MyViewController" bundle:nil];
MyAppDelegate *appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
MyObject *myO = (MyObject *)[appDelegate.myOs objectAtIndex:indexPath.row];
myViewController.amount = myO.amount;
[self.navigationController pushViewController:myViewController animated:YES];
[myViewController release];
如果我取消注释最后一行,那么在返回时应用程序会崩溃并显示错误:
-[CALayer release]: message sent to deallocated instance 0xd4f860

我进一步研究后发现崩溃可以进一步缩小到MyViewController的dealoc方法中调用[super dealoc]。取消注释"[super dealoc]"后,我们不会崩溃。

我无法进一步缩小问题范围。 "super"应该是UIViewController类,而我无法进一步调查那个dealoc方法……难道可以吗?也许有一种方法可以查看0xd4f860指向的具体内容,但我不知道怎么做?有什么想法吗?


你在任何地方发布 myViewController.view 吗? - Alice Isabelle
1个回答

4

你正在寻找错误的地方--问题在于我的视图控制器(myViewController)被释放(或自动释放)了太多次。

你发布的代码看起来是正确的,所以我会查看MyViewController的代码,看它是否曾经释放过自己,或者通过其他方式导致自己被释放。

你也可以重写release方法,设置一个断点,看看能否通过这种方式缩小范围......例如:

- (void)release {
    [super release]; //Set breakpoint here
}

刚刚尝试重写release方法并在那里打了一个断点...它在进入时被调用了21次(我猜测是由didSelectRowAtIndexPath触发),然后在退出视图时又调用了8次左右。不确定我应该寻找什么...里面有很多框架调用(“Purple”?!等等...) - Meltemi
mythogen 提出了一个很好的观点——你应该寻找视图被释放的地方(这最终会导致异常,当它尝试去释放已经消失的层时)。 - Daniel Dickison
找到问题了,我想。至少不会再崩溃了。我有两个UIView子类的实例,它们是MyVC视图的子视图...但也需要向上与MyVC通信,因此需要一个属性。根据您在此处的评论中的讽刺意味,我使用assign(而不是retain)设置了该属性:http://stackoverflow.com/questions/1145380。我明白为什么不应该保留VC,这样我就不会出现保留循环...但是没有它,我就会崩溃。显然,我仍然在这里误解了某些东西。如果您有时间,欢迎提供建议/批评... - Meltemi
刚刚重新阅读了Cocoa内存管理编程指南中关于保留循环的章节,是的,你说得对,“子视图”不应该保留它们的“父视图”。那么,当我将我的子视图分配给VC属性时,它们都没有在dealoc时释放,为什么会崩溃呢?然而,当我让它们都保留并释放时,一切都很顺利。抱歉我这么菜鸟...但我真的想理解这个问题... - Meltemi
1
这听起来像是你的自定义子视图在保留和释放其属性方面出了问题,或者它们可能会在应该被释放后仍然尝试向它们的代理(父视图)发送消息。你可能需要发布一些相关的子视图-父视图-控制器内存管理和消息传递代码。 - Daniel Dickison

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接