【发布时间】:2011-02-17 01:21:36
【问题描述】:
这是一个非常非常...非常奇怪的错误。很难描述我拥有的确切项目,但我会尝试创建一个更简单的类来表示我拥有的类。它是这样的:
假设我有一个导航控制器作为我的顶视图控制器。在其中,有一段时间我有一个 UIViewController,比如说一个 ContactsScreenController。此视图包含多个 UITableView,每个都由 MyTableController 类型的单独对象(委托和数据源)控制。我通过保留一组控制器来做到这一点
// This is the interface for my screen controller. An object of this type goes in a top-
// level navigation controller
// MainScreenController.h
@interface ContactsScreenController : UIViewController
NSMutableArray* tableControllers;
@end
// MainScreenController.m
- (UITableViewCell*)cellForRowAtIndexPath..something..
{
// Here what I do is create a new controller if needed, and add it to tableControllers
// Memory allocations & releases are good because I checked with instruments
}
#define SAFE_DEL(x) { if (x != nil) { [x release]; x = nil; } }
- (void)dealloc
{
SAFE_DEL(tableControllers);
[super dealloc];
}
现在,MyTableController 是一个更复杂的对象,因为它处理从 Web 服务获取数据,但基本上我要做的是确保在删除对象时,我会取消任何待处理的数据请求,如下所示:
// MyTableController.m
- (void)dealloc
{
[globalDataProvider cancelRequestsForController:self];
// release other objects i might have
[super dealloc];
}
好的,这就是我的对象设置。当我删除对象 tableControllers 时发生崩溃。它减少了 MyTableController 对象的 retainCount 并达到 0(使用 Instruments 检查)。但是由于一些未知的原因,在保留计数为零之后,我收到了对 cancelRequestsForController 的调用。 显然,我得到了 EXC_BAD_ACCESS。
在您开始认为这是我的保留/释放对有问题之前,如果我释放主屏幕控制器而内部表是静态的,则应用程序可以完美运行。一旦滚动并点击导航控制器中的后退按钮,我就会遇到错误。
我已经使用工具检查了我的内部控制器的保留计数更改的整个历史,这很好(没有不寻常的东西)。当错误发生时,我在历史记录中的最后一个条目来自 QuartzCore run_animation_callbacks,保留计数为 -1。
有什么想法吗? :)
PS:作为启动项目的快速解决方案,我已将 cancelRequestsForController 移至单独的方法中,并在发布前为 tableControllers 中的每个对象手动调用它。这样我就确定不管tableview的状态如何,发布后都不会再有调用了。
- (void)dealloc
{
for (TableController* c in tableControllers)
[c cancelRequests];
SAFE_DEL(tableControllers);
[super dealloc];
}
但我不喜欢这个解决方案有几个原因。
【问题讨论】:
标签: iphone uitableview crash scroll quartz-graphics