我正在尝试在后台运行同步引擎,我正在使用NSPrivateQueueConcurrencyType
这样:
- (NSManagedObjectContext *)workerContext
{
NSManagedObjectContext* workerContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
workerContext.parentContext = self.mainContext;
return workerContext;
}
我想我需要一个专用的后台队列,所以我也创建了这个:
- (dispatch_queue_t)syncQueue {
if (!_syncQueue) {
_syncQueue = dispatch_queue_create("com.me.syncEngineSyncQueue", 0);
}
return _syncQueue;
}
我遇到了一个NSManagedObject删除正在发生的问题,然而,它被颠倒了。我目前的猜测是它与线程有关。
我在同步引擎中记录了断点,发现同一个syncQueue
在不同的时间运行在不同的线程上。这可能是我的问题吗?
如果是这样,我如何创建一个在一个线程上一致运行的dispatch_queue?
答案 0 :(得分:0)
我认为我需要一个专用的后台队列,所以我已经创建了这个 以及:
Bzzzzt。错误。 Core Data会为您解决此问题。当您使用NSPrivateQueueConcurrencyType
初始化MOC时,它带有自己的内部管理的GCD队列。你根本不用担心它。
但是,任何与该MOC 相关的工作必须通过performBlock
NSManagedObjectContext
API完成。除其他外,该API基本上将您的块放在特殊的私有GCD队列上,并安排它执行。
如果是这样,我如何创建一个在一个上运行一致的dispatch_queue 线程?
你不是。这是GCD之美的一部分。您将代码块插入到消息队列中,并且"某些"线程将它们剥离并执行它们。您可能不太关心哪个线程正在这样做(主队列的东西除外)。
修改强>
疑难杂症。但是,我仍然需要保存mainContext 我的workerContext的父母,对吧?我是否需要拨打电话保存 主线程?现在我正在做[self.mainContext save:& error];在 使用后保存workerContext后的主线程 performBlockAndWait - Ramsel 5小时前
你最好将每个环境视为一个自己的实体,而且只有"才能利用"知道主要上下文在与UI元素交互时在主线程上运行,这需要在主线程上进行交互。
如果要在保存子项后保存父上下文,请执行以下操作,这是NSManagedObjectContext
上可能的类别方法。
- (void)_saveRecursively:(BOOL)recursiveSave
withCompletion:(void(^)(NSError *error))completion {
NSError *error;
if ([self save:&error]) {
error = nil;
NSManagedObjectContext *parent = self.parentContext;
if (parent != nil && recursiveSave) {
return [parent performBlock:^{
[parent _saveRecursively:recursiveSave withCompletion:completion];
}];
}
}
completion(error);
}
以上方法是"私人"不应暴露。它保存了当前的上下文。如果要求进行递归保存,它将继续保存层次结构,直到它结束,或者直到其中一个保存操作失败。
然后它将调用完成处理程序,如果失败则传递NSError
的实例,如果成功则传递nil
。
- (void)saveRecursively:(BOOL)recursiveSave
withCompletion:(void(^)(NSManagedObjectContext *moc, NSError *error))completion {
[self _saveRecursively:recursiveSave withCompletion:^(NSError *error) {
if (completion) {
[self performBlock:^{
completion(self, error);
}];
}
}];
}
此方法为用户提供类别API。它确保从原始保存上下文的受保护范围内异步调用完成块。这样,您可以保证可以安全地使用完成块,而无需再调用另一个performBlock
。
- (void)saveWithCompletion:(void(^)(NSManagedObjectContext *moc, NSError *error))completion {
[self saveRecursively:YES withCompletion:completion];
}
这提供了一种方便的方法来异步保存整个层次结构。
这意味着你可以这样调用save方法......
[childContext saveWithCompletion:^(NSManagedObjectContext *moc, NSError *error) {
// moc will be the same as childContext, and you can use the variable moc
// safely, knowing this block is running in its own performBlock
if (error) {
// Handle the save error
} else {
// Handle the successful save
}
}];