删除核心数据对象并保存在后台线程中



我仍然很难理解核心数据在背景线程中的工作方式,即使读取了很多内容,尤其是用于删除对象。

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

- (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。我尝试了数百件不同的事情,但我迷路了...谢谢!

您只能在context中删除object;在其中获取该托管对象。如果您使用的是带有新上下文的Seprate thread,则在这种情况下,您应该从managedObject获得objectId,从第一个上下文中获得,以便您可以删除对象

[context objectWithID:objectId]];

上下文之间的nsmanagedObjectID是相同的,但是nsmanagedObject本身不是。

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

您应该避免在任何UI面对的方法中避免使用昂贵的操作。删除后没有理由立即保存。稍后保存,当用户期望UI延迟时保存。核心数据将在没有保存的情况下正常工作。

在nsmanagedObjectContext上查看performblock和perfermblockandwait方法。

我一直喜欢使用nsprivatequeconconcurrencytype,即使是我的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];
    }
}

pertricblock调用是异步的(与同步的同步性绩效blockandwait),它将允许tableView更新继续进行,因为上下文忙于保存单独的线程。

顺便说一句,您的托管对象上下文实例不应经常更改。小型应用程序通常仅在其生命周期期间分配单个实例。

最新更新