I have a problem using a core data model in a table view. In the table view's commitEditingStyle: delegate method I first delete the model's object and then the corresponding row in the table view, similar to this:
- (void)tableVi开发者_运维问答ew:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
[self.managedObjectContext deleteObject:[self coreDataObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
}
}
But this raises an NSInternalInconsistencyException in the UITableView because the numberOfRowsInSection: delegate method return the wrong number of rows since the Core Data object hasn't been deleted yet.
How do I fix this "the official way"? Or the best way?
Do I have to track the NSManagedObjectContextObjectsDidChangeNotification notification and wait for the corresponding delete notification? It's doable, but can quiclky get quite messy.
Do I just wait and hope it's been deleted after a while? I have tested inserting a [self performSelector:withObject:afterDelay:] to delay the deletion of the table view row. And it works even with 0.0 delay. I presume the Core Data framework deletes the object after the current run loop has finished, but is this guaranteed? It could just as well just be pure coincidence.
Is the some other way to handle the situation? Would have been nice with a block completion API like deleteObject: withCompletionHandler:.
Any ideas?
/ Påhl
I'm assuming are you using FetchedResultsController
to fill your table with the core data objects. So the idea is that you need to implement the following method.
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath {
}
And in commitEditingStyle:
you just delete the object from managedObjectContext
and let the didChangeObject
delegate handle the table modifications for you.
Example implementation for didChangeObject
can be found here:
Apple's document
Obviously you have solved the problem by yourself, however the issue in your code is that are missing the part where you 'delete' the object from the datasource. In
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath`
you have to put:
if (editingStyle == UITableViewCellEditingStyleDelete) {
// delete obj from the context
[self.managedObjectContext deleteObject:[self coreDataObjectAtIndex:indexPath.row];
// REMOVE obj from the dataSource (dataSource is your NSArray or NSMutableArray where are stored the objects
[dataSource removeObjectAtIndex:indexPath.row];
// then refresh the tableView
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
}
精彩评论