上下文:使用Core Data,我在专用队列上有一个主上下文(我将称为mainContext),在主队列上还有一个上下文,即主队列的子级(我将称为childContext)。队列无关紧要,我的问题的答案不应取决于上下文所在的队列。

我的目标是将childContext的修改直接保存到磁盘上,而在mainContext带来的修改保存到磁盘之前,不要让childContext进行任何修改。

为此,我致电:

[self.childContext performBlockAndWait:^{
  [self.parentContext performBlockAndWait:^{
    [self.childContext save:NULL];
    [self.parentContext save:NULL];
  }];
}];


其背后的想法是,如果我同时执行一个块并在子级和父级上下文上等待,则在保存子级时不能对主上下文进行任何修改。然后保存主上下文,然后退出块。该文档明确指出,对performBlockAndSave:的调用是可重入的,因此应该可以使用。

可以?对performBlockAndWait:的嵌套调用是否有效?显然,保存是在mainContext队列上完成的,并且childContext队列在保存期间未锁定。正常吗如果是这样,我如何实现我的目标?



注意:由于我与API通信的方式,我需要这种原子性。要在我的API上创建对象,我先在本地创建对象,然后检查Core Data上下文中的本地修改,然后将这些修改转换为API调用。如果我打电话给:

[self.childContext performBlockAndWait:^{
  [self.childContext save:NULL];
  /* 1 */
  [self.parentContext performBlockAndWait:^{
    [self.parentContext save:NULL];
  }];
}];


performBlock:保存mainContext之前(在performBlockAndWait:处),有可能在mainContext上调用1。该调用将具有“不干净”的上下文,childContext中的更改将等待保存到磁盘上。

最佳答案

我认为解决方案是在上下文层次结构中进一步创建更多子上下文。

为了清楚起见,请允许我重命名您的上下文:

让我们将mainContext称为rootContext(背景,保存到持久性存储中)。
让我们将childContext称为mainContext(主线程上下文,rootContext的子代)。
让我们将任何较低的子级上下文称为“工作人员上下文”(背景,mainContext的子级)。

工作程序上下文应为以主要上下文为父级的背景上下文。

您可以在中心位置放置根上下文将其保存到物理存储,例如您可以在其中管理核心数据堆栈。

据我了解,当通过save:将更改从工作人员上下文推送到主上下文时,同时主上下文本身在performBlockAndWait块中将更改推送到其父上下文,它将仅获得完成后更改。只有这样,它才能将它们进一步推向要物理保存的根上下文。我认为这应该可以实现您的原子性目标。

通过引入辅助上下文,您可以确保根上下文不会从主上下文接收任何其他更新。

10-08 18:04