0

我创建了一个带有自定义笔尖的 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;

注意[单元保留];行 - 当它在那里时,代码可以流畅地工作。把它拿出来,然后崩溃。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

即使它适用于 [细胞保留]; 行,它看起来像是分析(和我)的泄漏,所以我想解决这个问题。有人知道这里发生了什么吗?

4

1 回答 1

2

不要调用retainCount

绝对保留计数是无用的。

([cell retainCount] < 1)不可能工作; retainCount永远不能返回零。

(是的——加载一个笔尖cellForRowAtIndexPath:现在得到了框架的祝福。Coolio。)

那么,您的问题在于其他地方,因为该代码(没有保留)是正确的。

它仍然很可能是在常规事件循环耗尽之前发生的自动释放池耗尽。特别是,某处的某处对不应该的单元格有弱引用。

如果您启动分配工具并打开保留/释放事件记录,您可以准确地看到对保留/释放/自动释放对象的调用发生的位置。导致崩溃的事件具有明显的价值。

但是,在这种情况下,您可能在某处缺少保留/释放对。至少,这可以解决症状。真正的问题可能是发生了某种 UI 转换,使得某些内容实际上过早地获得,而您的应用程序的某些其他部分仍然依赖于它。添加一个保留/释放对以便在该转换期间保留单元的生命周期并不是真正的修复,因为可能存在其他依赖项。

于 2011-04-29T17:22:50.343 回答