重复调用UINavigationController的push会导致访问错误

重复调用UINavigationController的push会导致访问错误,uinavigationcontroller,ios,exc-bad-access,Uinavigationcontroller,Ios,Exc Bad Access,我有一个TabView应用程序,它有一个选项卡,其中一个视图是NavView。此视图有一个子视图,其中包含用于保存事件的TableView。我已启用导航栏右上角的“添加”按钮,并将iAction分配给该按钮 目标是显示一个页面,以添加一个新事件,该事件由我实例化子类控制器类的实例时加载的NIB文件定义。我还从父导航控制器传递managedObjectContext 第一次可以,但第二次按下“添加”按钮时,会出现EXC\u BAD\u访问错误。我已经调试好了控制器到导航控制器的推送,我已经确认这就

我有一个TabView应用程序,它有一个选项卡,其中一个视图是NavView。此视图有一个子视图,其中包含用于保存事件的TableView。我已启用导航栏右上角的“添加”按钮,并将iAction分配给该按钮

目标是显示一个页面,以添加一个新事件,该事件由我实例化子类控制器类的实例时加载的NIB文件定义。我还从父导航控制器传递managedObjectContext

第一次可以,但第二次按下“添加”按钮时,会出现EXC\u BAD\u访问错误。我已经调试好了控制器到导航控制器的推送,我已经确认这就是异常发生的地方。我读过文件,上面说导航控制器会通过点击导航栏顶部的“后退”按钮弹出控制器。我还知道,如果我尝试将相同的视图推送到堆栈上,将发生未处理的异常。我甚至尝试在清除堆栈的推送之前弹出到根目录,但在第二次推送时仍然会出现异常

我是否应该在其他地方手动弹出此按钮(即导航“后退”按钮实际上没有弹出此按钮)?我还确认了导航控制器和新实例化的视图控制器的实例都不是空的

以下是“添加”按钮的代码段:

- (IBAction) addEvent: (id)sender {

 // Here we'd instantiate an instance of our Add Event Controller to show the form that allows us to enter a new event.

 // We'd add the context to the class from here so that it can get to our Core Data


  EventEntryViewController *fvController = [[EventEntryViewController alloc] initWithNibName:@"AddEventView" bundle:nil];

 fvController.managedObjectContext = self.managedObjectContext;

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

 [fvController release];

 fvController = nil;

}
谢谢你的帮助

更新:

好的,我已经阻止了异常的发生。我尝试了一个非常简单的视图,其中没有任何内容,也没有IBOutlets或IBActions,还有一个没有属性的控制器类。这很有效,所以我想这一定是我的EventEntryViewController的问题。它做的不多,回溯显示它在显示视图的内部正在消亡,所以我甚至没有使用loadView方法,更不用说代码的任何其他部分了。我有一些在上一次加载中初始化的类属性,作为一个好公民,我在viewDidUnload()中释放了它们,并在dealloc()中释放了它们。当我注释掉类属性的dealloc时,它起作用了

我对此感到困惑,并将NSLog()行放在viewDidLoad()、viewDidUnload()和dalloc()中。以下是我取出类属性的dalloc后的两个推送序列的结果:

2010-09-18 20:17:46.224 myFuel[6435:207] EventTableNavViewController: viewDidAppear
2010-09-18 20:17:51.391 myFuel[6435:207] **EventEntryViewController**: View Did Load // loading up my class
2010-09-18 20:17:53.954 myFuel[6435:207] EventTableNavViewController: viewWillAppear
2010-09-18 20:17:54.314 myFuel[6435:207] EventTableNavViewController: viewDidAppear
2010-09-18 20:17:54.315 myFuel[6435:207] **EventEntryViewController**: dalloc       // after the class should have been popped
2010-09-18 20:18:02.803 myFuel[6435:207] **EventEntryViewController**: View Did Load //loading up my class
2010-09-18 20:18:08.134 myFuel[6435:207] EventTableNavViewController: viewWillAppear
2010-09-18 20:18:08.494 myFuel[6435:207] EventTableNavViewController: viewDidAppear
2010-09-18 20:18:08.495 myFuel[6435:207] **EventEntryViewController**: dalloc    // after the class should have been popped

我是不是遗漏了什么?视图不应该调用viewDidUnload()从而释放类属性吗?我可以看到dealloc被调用,但是我在哪里发布这些呢?

基于您所说的一些事情,尽管我不清楚您到底在做什么

首先,
viewDidUnload:
不保证被调用。通常,只有当视图控制器响应内存警告卸载其视图时,才会调用它。因此,在
viewdiload:
中保留引用的任何内容或连接的任何IBOutlets都应在
viewdiload:
dealloc
中释放


第二,您在引用“类属性”时说“在dealloc中释放它们”,我认为这意味着您实际上在对其他对象调用
dealloc
。如果是的话。。。不要那样做。您必须仅对保留的对象调用
release
,直接调用
dealloc
时很少有实例。这是因为当对象最后一次被释放时,将在对象的
release
实现中调用
dealloc
。这就是保留/释放系统的全部要点。

谢谢。我一直在阅读Objective-C中的内存管理,特别是在iOS框架中。我必须深入研究微软COM旧世界中关于参考计数的神经突触,才能让灯泡熄灭。需要明确的是,在正常操作中,会调用dealloc,并且我的释放(如果它是对象的最后一个引用)将被拾取。在出现内存警告时,将调用viewDidUnload,并且那里的发布将允许GC清理内容。问题是,在最后一种情况下,viewDidUnload和dealloc是否会被调用,并且后续的版本会导致异常?当您在
viewDidUnload:
中发布时,请确保也将引用设置为
nil
。然后,当在
dealloc
中调用
release
时,您将不会在悬空引用上调用release。例如,如果您有一个
ibuilabel*标签
,从'viewDidUnload:`开始,您将执行:
[label release];标签=零和您的
dealloc
中的相同代码。如您所知,您可以安全地向
nil
引用发送消息,这就是
dealloc
中的发布是安全的原因。