Eric
Eric

Reputation: 3363

Yet another NSInternalInconsistencyException, but using NSFetchedResultsController

I've gone through many of the questions/answers related to NSInternalInconsistencyException / NSFetchedResultsController, but I can't find anything to help me solve my problem.

I get this error after deleting a row in my TVC: Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 0

Here's the method in charge of performing the deletion on the data source

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        [self.tableView beginUpdates];

        Role *roleToDelete = [self.fetchedResultsController objectAtIndexPath:indexPath];
        NSLog(@"Deleting: %@", roleToDelete.name);
        [self.managedObjectContext deleteObject:roleToDelete];
        [self.managedObjectContext save:nil];
        // Delete the row from the data source
        // [self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
        [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
        [self performFetch];

        [self.tableView endUpdates];
    }
}

My Exception Breakpoint stops at the last line of this method. The weird thing is that the debugger says that I'm deleting two rows, which I'm not:

The number of rows contained in an existing section after the update (1) must be equal to the number of rows contained in that section before the update (2), plus or minus the number of rows inserted or deleted from that section (0 inserted, 2 deleted)

The next time I start the app, it is clear that only one row was deleted.

Here are the other methods that could cause a problem:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return [[self.fetchedResultsController sections] count];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [[[self.fetchedResultsController sections] objectAtIndex:section] numberOfObjects];
}

Upvotes: 1

Views: 622

Answers (1)

Martin R
Martin R

Reputation: 539765

The fetched results controller (FRC) updates the table view automatically if an object is inserted, deleted or changed. Therefore, you just have to delete the object:

Role *roleToDelete = [self.fetchedResultsController objectAtIndexPath:indexPath];
[self.managedObjectContext deleteObject:roleToDelete];
[self.managedObjectContext save:nil];

Everything else (beginUpdates, deleteRowsAtIndexPaths:..., endUpdates) is done in the FRC delegate methods (controllerWillChangeContent:, didChangeObject:..., controllerDidChangeContent:). It should also not be necessary to call performFetch.

In your case, deleteRowsAtIndexPaths:... is called twice: Once in your commitEditingStyle: method and a second time in the FRC delegate method didChangeObject:.... This causes the "internal inconsistency exception".

Upvotes: 2

Related Questions