我将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]
并添加到它,我已将我的块添加到队列的末尾。我真正想要的是恢复。
我应该在这里使用什么方法?
答案 0 :(得分:1)
你的第一种方法是我会使用的方法。但是,您提到了对performBlockAndWait:
内部死锁的担忧。您是否担心调用可能自己使用performBlockAndWait:
的另一种方法?如果是这样,不用担心; performBlockAndWait:
显然可以安全地使用。那就是:这段代码是安全的(虽然显然是做作的):
[context performBlockAndWait:^{
[context performBlockAndWait:^{
// fetch someValue from Core Data
}];
}];
如果死锁问题与核心数据无关,那么您doMoreWorkWithValue:
内部的死锁风险似乎也一样,对吧?