I'm at a loss! It's one of those pesky bugs that happens only under specific conditions, yet I cannot link the conditions and the results directly.
My app has a paged UIScrollView where each page's view comes from a MyViewController, a subclass of UITableViewController. To minimize memory usage I unload those controllers that are not currently visible. Here is my "cleaning" method:
- (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]];
}
}
It's this line that crashes the app:
viewControllers replaceObjectAtIndex:i withObject:[NSNull null]];
viewControllers is an NSMutableArray containing objects of type MyViewController. MyViewController has no custom properties and its dealloc method contains nothing but a [super dealloc] call.
Here is what the debugger shows:
The thing is that this does not happen every time the controller is cleared, but only sometimes. Specifically, after certain changes trigger a complete cleaning and re-drawing of the ScrollView, it displays the current page (call it X) fine, but as soon as I scroll far enough to cause cleaning of X, this crash happens. It's driving me nuts!
Another thing, this does not happen in the 4.0 Simulator, nor on an iPad, but happens very consistently on a 1st gen iPod touch running 3.1.3.