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