tableView endUpdates crashes after change in fetchedResults
I have an app which shows a custom no-data-yet cell when the user first launches the app.
When the user makes the first entry the fetchedResults of my fetchedResultsController gets updated, which causes the no-data-yet cell to be deleted and a data cell to be 开发者_运维百科inserted.
this used to work in the past (iPhone 3.x). Now on iOS 4.2, it results in a crash after endUpdates gets called. There is no exception information or any kind of intelligible stack trace. I only know the crash is caused in _CFTypeCollectionRetain (possibly trying to retain a NULL)
Any ideas how to proceed?
here is the relevant code:
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
NSLog(@"starting updates");
[self.tableView beginUpdates];
}
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {
switch(type) {
case NSFetchedResultsChangeInsert:
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath {
UITableView *tv = self.tableView;
[tv reloadData];
switch(type) {
case NSFetchedResultsChangeInsert:
NSLog(@"insert");
if ([self.tableView numberOfRowsInSection:newIndexPath.section] == 1 &&
[[self.fetchedResultsController fetchedObjects] count] == 1)
{
NSLog(@"reloading row %d", newIndexPath.row);
[tv deleteRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
[tv insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
}
else {
NSLog(@"inserting new row %d", newIndexPath.row);
[tv insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
}
break;
case NSFetchedResultsChangeDelete:
NSLog(@"delete");
if ([self.tableView numberOfRowsInSection:newIndexPath.section] == 0 &&
[[self.fetchedResultsController fetchedObjects] count] == 0)
{
NSLog(@"reloading row %d", newIndexPath.row);
[tv deleteRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
[tv insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
}
else {
NSLog(@"deleting row %d", newIndexPath.row);
[tv deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
break;
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
NSLog(@"finishing updates");
[self.tableView endUpdates];
}
In the delegate method
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath
you handle insertions and deletions. For insertions indexPath
is nil
. And for deletions newIndexPath
is nil
. So you are not allowed to access the newIndexPath
in case of type== NSFetchedResultsChangeDelete
.
Besides the call to reloadData
is not necessary here.
精彩评论