删除Core Data对象并保存在后台线程中

时间:2014-01-20 22:47:39

标签: ios multithreading core-data background-thread

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

例如,如果我想从上下文中删除对象:

- (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。 我尝试了数百种不同的东西,但我迷失了...... 谢谢!

3 个答案:

答案 0 :(得分:1)

您只能删除object中的context;您在其中获取该托管对象。如果你使用seprate thread和新的上下文,那么你应该从第一个上下文得到objectId managedObject,这样你就可以删除对象

[context objectWithID:objectId]];

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

答案 1 :(得分:1)

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

你应该避免在任何面向这样的方法调用的UI中进行昂贵的操作。删除后没有理由立即保存。稍后保存,在用户期望UI延迟时保存。核心数据在没有保存的情况下可以正常工作。

答案 2 :(得分:0)

查看NSManagedObjectContext上的performBlock和performBlockAndWait方法。

我一直偏爱使用NSPrivateQueueConcurrencyType,即使对于我的UI绑定托管对象上下文也是如此,因为它避免了这种情况。例如,您可以这样做:

- (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实例。