在异步操作中使用Core Data

时间:2017-01-31 17:13:19

标签: multithreading core-data nsoperation

我将iOS同步过程分解为一系列异步NSOperation子类。这些细分为重处理和依赖网络的处理。但他们中的大多数人也使用Core Data做事。

我不确定如何在操作中执行核心数据操作。

这里有几个简单的例子......我的真实代码在数据库上下文中进行了几次切换。它还使用@synchronize(self){}

NSManagedContext *context = [self newContextFromParent];
__block NSString *someValue;
[context performBlockAndWait:^{
    // fetch someValue from Core Data
}];
[self doMoreWorkWithValue:someValue];
[context performBlockAndWait:^{
    NSError *e;
    if ([context hasChanges]) {
        [context saveChanges:&e];
    }
}];

这似乎表面上看起来很好,但取决于我在performBlockAndWait:中所做的事情,这里存在潜在的死锁。

通常,我希望在代码中避免使用performBlockAndWait:,而是使用performBlock:

[context performBlock:^{
    NSString *someValue = @""; // fetch someValue from Core Data
    [backgroundQueue addOperationWithBlock:^{
        [self doMoreWorkWithValue:someValue withCompletion:^{
            [context performBlock:^{
                NSError *e;
                if ([context hasChanges]) {
                    [context saveChanges:&e];
                }
            }];
        }];
    }];
}];

但是,通过这种方法,我将处理从我给出的线程移到任何线程backgroundQueue决定运行我的进程,我不确定更好的方法是什么。

如果我在主操作中捕获[NSOperation currentQueue]并添加到它,我已将我的块添加到队列的末尾。我真正想要的是恢复。

我应该在这里使用什么方法?

1 个答案:

答案 0 :(得分:1)

你的第一种方法是我会使用的方法。但是,您提到了对performBlockAndWait:内部死锁的担忧。您是否担心调用可能自己使用performBlockAndWait:的另一种方法?如果是这样,不用担心; performBlockAndWait:显然可以安全地使用。那就是:这段代码是安全的(虽然显然是做作的):

[context performBlockAndWait:^{
    [context performBlockAndWait:^{
        // fetch someValue from Core Data
    }];
}];

如果死锁问题与核心数据无关,那么您doMoreWorkWithValue:内部的死锁风险似乎也一样,对吧?