Reputation: 5132
I am creating a core data example wherein I want to delete managed objects (here called projects). Deleting the manages objects seems to work, but refreshing the tableView is a problem. Below is the log message I get when the app crashes when tableView: numberOfRowsInSection:
is called.
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (13) must be equal to the number of rows contained in that section before the update (13), plus or minus the number of rows inserted or deleted from that section (0 inserted, 1 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).'
Here the number of rows before the deletion is 14 and after is 13. See the methods I am using for A. fetching the number of rows, which should equal the number of "projects" in core data. B. Deleting the project. C. setting the number of rows in the tableView.
A.
-(void) setupFetchResultsController {
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Project"];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES];
request.sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSError *error;
fetchedProjects = [managedObjectContext executeFetchRequest:request error:&error];
if (fetchedProjects == nil) {
// Handle the error.
}
self.fetchedResultsController = [[NSFetchedResultsController alloc]initWithFetchRequest:request managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:nil];
}
B.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
selectedProject = [self.fetchedResultsController objectAtIndexPath:indexPath];
[managedObjectContext deleteObject:selectedProject];
//setting up the fetch results controlleris intended to get the number rows correctly by fetching the existant projects. In the above log, the result would be 14 (not 13) without this line. Crashes with or without this line.
[self setupFetchResultsController];
if (editingStyle == UITableViewCellEditingStyleDelete) {
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
}
C.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
int noOfRows = [[[self.fetchedResultsController sections] objectAtIndex:section] numberOfObjects];
return noOfRows;
}
Upvotes: 1
Views: 903
Reputation: 5132
The problem was, I think, that I did not need to manually delete the row using:
if (editingStyle == UITableViewCellEditingStyleDelete) {
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
I think the FetchResultsController takes care of that. Anyway I removed the line and it works.
Upvotes: 1
Reputation: 1843
This has nothing to do with Core Data.
You must ensure the number of rows in the table and the number of rows in the data source is always the same.
If you need to delete a row, you need to delete the row from the data source, delete it from the table, BUT -> you need to do it between those two lines of code:
[_tableView beginUpdates];
// here delete from data source, and from the table.
[_tableView endUpdates];
Upvotes: 2