我不知所措!这是仅在特定条件下发生的那些讨厌的错误之一,但我无法直接链接条件和结果。
我的应用程序有一个分页的UIScrollView,其中每个页面的视图来自一个MyViewController,一个UITableViewController的子类。为了最小化内存使用量,我卸载那些当前不可见的控制器。这是我的“清洁”方法:
- (void) cleanViewControllers:(BOOL)all {
if (all) {
// called if some major changes occurred and ALL controllers need to be cleared
for (NSInteger i = 0; i < [viewControllers count]; i++)
[viewControllers replaceObjectAtIndex:i withObject:[NSNull null]];
}
else if ([viewControllers count] > 2) {
// called if only the nearest, no longer visible controller need to be cleared
NSInteger i = pageControl.currentPage - 2;
if (i > -1) [viewControllers replaceObjectAtIndex:i withObject:[NSNull null]];
i = pageControl.currentPage + 2;
if (i < [viewControllers count]) [viewControllers replaceObjectAtIndex:i withObject:[NSNull null]];
}
}
这条线崩溃了应用程序:
viewControllers replaceObjectAtIndex:i withObject:[NSNull null]];
viewControllers是一个NSMutableArray,包含MyViewController类型的对象。 MyViewController没有自定义属性,其dealloc方法只包含[super dealloc]调用。
这是调试器显示的内容: alt text http://a.imageshack.us/img831/3610/screenshot20100806at126.png
事情是,每次清除控制器时都不会发生这种情况,但有时只会发生。具体来说,在某些更改触发完全清理并重新绘制ScrollView后,它会显示当前页面(称为X),但是只要我滚动到足以导致X的清理,就会发生此崩溃。这让我疯了!
另一件事,这不会发生在4.0模拟器中,也不会发生在iPad上,而是在运行3.1.3的第一代iPod touch上非常一致。
答案 0 :(得分:6)
有些东西正在被释放,但指针仍悬空。将NSZombieEnabled设置为YES并再次运行它。方法如下:
在Xcode 4.1及以上版本中:
再次运行该应用。在某些时候它会告诉你你正在访问已经发布的对象。从那里你需要弄清楚谁不保留或谁过度释放对象。
快乐的僵尸狩猎。
答案 1 :(得分:1)
通常这可以通过分配一些内容然后将其设置为ViewController中的内容然后释放它来引起,例如:
UIBarButtonItem* timeLabel = [[UIBarButtonItem alloc] initWithTitle:@"time" style:UIBarButtonItemStylePlain target:nil action:nil];
NSArray *items = [NSArray arrayWithObjects: timeLabel, nil];
self.toolbarItems = items;
现在自然要做的就是:
[timeLabel release];
但这会导致[super dealloc]上的EXC_BAD_ACCESS,大概是因为视图控制器释放了数组及其中的所有项目。
答案 2 :(得分:0)
默认情况下,View控制器会自动卸载内存警告上的视图,因此除非它们包含大量开销,否则没有理由自行卸载控制器。
视图控制器的视图是否仍在视图层次结构中?您可以查看[viewController isViewLoaded] && viewController.view.superview
之类的内容。如果是这样,删除视图控制器可能不安全。
(注意isViewLoaded检查,因为如果视图尚未加载,UIViewController.view将加载视图。)
答案 3 :(得分:-1)
您可以简单地调用removeObjectAtIndex:
或removeAllObjects:
,而不是替换数组中的元素,以确保没有任何内容可以保留参考。