Reputation: 2130
I've created a UITAbleViewCell subclass with a custom nib, and am using it in two different UITableViews in my app. It works perfectly in one of the tables, but the other table crashes when I scroll it vigorously. Instruments identifies a zombie in this code (in 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;
Notice the [cell retain]; line - when it's in there, the code works swimmingly. Take it out, and crash. NSLog always reports a retainCount of 2, so it shouldn't be necessary. But if I do something like this:
if ([cell retainCount] < 1) { [cell retain]; } // does not prevent zombies!
it doesn't work. There's no alloc/init, so I shouldn't have to do an autorelease or worry about this at all, and I've always thought that cellForRowAtIndexPath releases the cell for me.
When I'm not using Instruments, here's the error I get from xcode:
*** -[CALayer retain]: message sent to deallocated instance 0x4d8e930
Even though it works with the [cell retain]; line, it looks like a leak to Analyze (and to me), so I'd like to resolve the problem. Anyone know what's going on here?
Upvotes: 1
Views: 613
Reputation: 162722
The absolute retain count is useless.
([cell retainCount] < 1)
cannot possibly work; retainCount
can never return zero.
(Yup -- loading a nib in cellForRowAtIndexPath:
is now blessed by the framework. Coolio.)
Your problem, then, lies elsewhere as that code (without the retain) is correct.
It is still quite likely to be an autorelease pool drain that is happening before the regular event loop drain. In particular, something somewhere has a weak reference to the cell that shouldn't.
If you fire up the Allocations Instrument and turn on retain/release event recording, you can see exactly where the calls to retain/release/autorelease the object occur. The event that causes the crash is of obvious value.
In this case, though, you are probably missing a retain/release pair somewhere. At least, that would be a fix for the symptoms. The real problem is likely some kind of UI transition that happens such that some contents are effectively prematurely reaped while some other section of your app still has dependencies on it. Adding a retain/release pair such that the lifespan of the cell is preserved across that transition isn't really a fix in that there may be other dependencies.
Upvotes: 2