Objective c 核心数据保存但不保存-专用队列跳转线程

Objective c 核心数据保存但不保存-专用队列跳转线程,objective-c,multithreading,core-data,grand-central-dispatch,Objective C,Multithreading,Core Data,Grand Central Dispatch,我尝试在后台运行同步引擎,并使用NSPrivateQueueConcurrencyType如下所示: - (NSManagedObjectContext *)workerContext { NSManagedObjectContext* workerContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; workerContext.

我尝试在后台运行同步引擎,并使用
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
在不同的时间在不同的线程上运行。这可能是我的问题吗

如果是这样,我如何创建在一个线程上一致运行的调度队列

我想我需要一个专用的后台队列,所以我创建了这个 以及:

Bzzzzt。错。核心数据为您解决这一问题。当您使用
NSPrivateQueueConcurrencyType
初始化MOC时,它附带了自己的内部管理GCD队列。你一点也不介意

但是,必须通过
NSManagedObjectContext
performBlock
API完成与该MOC相关的任何工作。除其他外,该API基本上将块放在特殊的专用GCD队列上,并安排它执行

如果是这样,我如何创建一个调度队列,该队列在一台计算机上一致运行 线

你没有。这就是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
    }
}];

明白了。但是,我仍然需要保存
mainContext
,它是我的
workerContext
的父级,对吗?我需要在主线程中调用save吗?现在我正在执行
[self.mainContext save:&error]performBlockAndWait保存
workerContext
后,在主线程中执行code>