我用自定义nib创建了一个UITAbleViewCell子类,并在我的应用程序中的两个不同的UITableViews中使用它。它在其中一个表中完美运行,但是当我用力滚动它时,另一个表崩溃了。 Instruments在此代码中标识了一个僵尸(在cellForRowAtIndexPath中):
NSString *identifier = @"edit";
LogTableCell *cell = (LogTableCell*)[tableView dequeueReusableCellWithIdentifier:identifier];
if (!cell) {
cell = (LogTableCell*) [[[NSBundle mainBundle] loadNibNamed:@"LogTableCell" owner:self options:nil] objectAtIndex:0];
[cell retain]; // prevents zombies!
}
NSLog(@"%@: retainCount: %d", identifier, [cell retainCount]);
// some other cell init stuff
return cell;
注意[cell retain]; line - 当它在那里时,代码在游泳中运行。拿出来,崩溃。 NSLog始终报告retainCount为2,因此不需要。但如果我做这样的事情:
if ([cell retainCount] < 1) { [cell retain]; } // does not prevent zombies!
它不起作用。没有alloc / init,所以我根本不需要做自动释放或担心这一点,我一直以为cellForRowAtIndexPath会为我释放单元格。
当我不使用Instruments时,这是我从xcode获得的错误:
*** -[CALayer retain]: message sent to deallocated instance 0x4d8e930
即使它适用于[cell retain];对于分析(对我而言),它看起来像是泄漏,所以我想解决这个问题。有谁知道这里发生了什么?
答案 0 :(得分:2)
绝对保留计数没用。
([cell retainCount] < 1)
不可能奏效; retainCount
永远不会返回零。
(是的 - 在cellForRowAtIndexPath:
加载一个笔尖现在受到框架的祝福.Coolio。)
然后,您的问题出在其他地方,因为该代码(没有保留)是正确的。
在常规事件循环流失之前,它仍然很可能是自动释放池流失。特别是某些地方的某些东西对细胞的弱引用不应该。
如果启动分配工具并打开保留/释放事件记录,则可以确切地看到保留/释放/自动释放对象的调用的位置。导致崩溃的事件具有明显的价值。
但是,在这种情况下,您可能错过了某处的保留/释放对。至少,这将是症状的解决方法。真正的问题可能是某种类型的UI转换发生,使得某些内容有效地过早收获,而您的应用程序的某些其他部分仍然依赖于它。添加一个保留/释放对,以便在该转换过程中保留单元的生命周期并不是一个真正的修复,因为可能存在其他依赖关系。