开发者

Core Data: when is deleteObject: done?

开发者 https://www.devze.com 2023-04-11 02:53 出处:网络
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,

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?

  1. Do I have to track the NSManagedObjectContextObjectsDidChangeNotification notification and wait for the corresponding delete notification? It's doable, but can quiclky get quite messy.

  2. 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.

  3. 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];
  }
0

精彩评论

暂无评论...
验证码 换一张
取 消