I have a rather vanilla UITableView
managed by an NSFetchedResultsController
to display all instances of a given Core Data entity.
When the user deletes an entry in the table view by swiping over it, tableView:cellForRowAtIndexPath:
eventually gets called on my UITableViewController
with a nil
indexPath
. Since I had not expected it to be called with a nil
indexPath
, the app crashes.
I can work around the crash by checking for that nil
value and then returning an empty cell. This seems to work, but I still worry that I may have handled something wrong. Any ideas? Has anybody ever seen tableView:cellForRowAtIndexPath:
called with a nil
indexPath
?
Note that this only happens when the user deletes from the table view by swiping over the cell. When deleting an item using the table view editing mode, it doesn't happen. What would be different between the two ways to delete a cell?
So is it really an OK situation to get a nil
indexPath
in a table view delegate method?
My view controller code is really standard. Here is the deletion:
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
NSManagedObject *managedObject = [self.fetchedResultsController objectAtIndexPath:indexPath];
[self.moc deleteObject:managedObject];
NSError *error = NULL;
Boolean success = [self.moc save:&error];
if (!success) { <snip> }
// actual row deletion from table view will be handle from Fetched Result Controller delegate
// [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
} else { <snip> }
}
This will lead to the NSFetchedResultsController
delegate method being called:
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath
{
UITableView *tableView = self.tableView;
switch(type) {
case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeInsert: <snip> break;
case NSFetchedResultsChangeUpdate: <snip> break;
case NSFetchedResultsChangeMove: <snip> break;
}
}
And of course, the data source methods are handled by the NSFetchedResultsController
, e.g.:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section];
return [sectionInfo numberOfObjects];
}
Many thanks.
It seems like you are deleting the indexPath from table but table data source is not updating. Did you verify the data source udation process by NSFetchedResultsController is correctly updationg the table data source.?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With