0

即使在阅读了很多关于它的内容之后,我仍然很难理解核心数据在后台线程中的工作原理,尤其是对于删除对象。

例如,如果我想从这样的上下文中删除一个对象:

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSManagedObjectContext *context = [self managedObjectContext];
    if (editingStyle == UITableViewCellEditingStyleDelete)
    {
        // Delete object from database
        [context deleteObject:[self.tests objectAtIndex:indexPath.row]];
        NSError *error = nil;
        if (![context save:&error]) {
            NSLog(@"Can't Delete! %@ %@", error, [error localizedDescription]);
            return;
        }
        [self.tests removeObjectAtIndex:indexPath.row];
        [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
    }
}

这行得通,但是当数据很大时,[context save:&error]会花费很多时间,那么我该如何在后台进行呢?似乎我无法使用其他上下文,否则我会收到错误消息an nsmanagedobjectcontext cannot delete objects in other contexts。我已经尝试了数百种不同的东西,但我迷路了......谢谢!

4

3 回答 3

2

您只能objectcontext;中删除 您在其中获取了该托管对象。如果您在thread新上下文中使用单独的,在这种情况下,您应该objectIdmanagedObject第一个上下文中获取,以便您可以删除对象

[context objectWithID:objectId]];

NSManagedObjectID 在上下文之间是相同的,但 NSManagedObject 本身不是。

于 2014-01-20T22:56:09.577 回答
1

正如提到的另一个答案,您只能从其上下文中删除一个对象,并且上下文是线程绑定的。这里的问题不是保存需要多长时间,而是您在哪里保存。

您应该避免在像这样的任何面向 UI 的方法调用中进行昂贵的操作。删除后没有理由立即保存。稍后保存,当用户期望 UI 出现延迟时保存。无需保存,Core Data 就可以正常工作。

于 2014-01-21T02:37:05.550 回答
0

看看 NSManagedObjectContext 上的 performBlock 和 performBlockAndWait 方法。

即使对于我的 UI 绑定托管对象上下文,我也一直倾向于使用 NSPrivateQueueConcurrencyType,因为它完全避免了这种情况。例如,您可以执行以下操作:

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSManagedObjectContext *context = [self managedObjectContext];
    if (editingStyle == UITableViewCellEditingStyleDelete)
    {
        NSManagedObject *m = [self.tests objectAtIndex:indexPath.row];
        [context performBlock:^{
            [context deleteObject:m];

            if (![context save:&error]) {
                //Note: You should really do something more useful than log this
                NSLog(@"Can't Delete! %@ %@", error, [error localizedDescription]);
            }
        }];
        [self.tests removeObjectAtIndex:indexPath.row];
        [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
    }
}

performBlock 调用是异步的(与其同步对应的 performBlockAndWait 不同),这将允许 tableView 更新继续进行,因为上下文正忙于保存在单独的线程上。

顺便说一句,您的托管对象上下文实例不应该经常更改。小型应用程序在其生命周期内只分配一个 NSManagedObjectContxt 实例是很常见的。

于 2014-01-21T07:13:21.043 回答