将主上下文和私有上下文与 Core Data 合并

Posted

技术标签:

【中文标题】将主上下文和私有上下文与 Core Data 合并【英文标题】:Merging main and private contexts with Core Data 【发布时间】:2015-08-25 08:19:35 【问题描述】:

我正在私有队列中创建临时上下文,以异步更新我使用Core Data 持久保存的数据:

NSManagedObjectContext *privateContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
privateContext.persistentStoreCoordinator = appDelegate.persistentStoreCoordinator;

[privateContext performBlock: ^

    // Parse files and/or call services and parse
    // their responses

    dispatch_async(dispatch_get_main_queue(), ^
        // Notify update to user
    );
];

然后,一旦我获得了新数据,我需要将更改与我的主要上下文合并。我知道这是一种常见的情况,但我不确定我应该如何继续......这个 Apple 的核心数据文档section 谈到了设置合并策略,我不完全理解处理它的方法。另一方面,我发现了这个link,我的场景在它的“堆栈#2”部分中进行了描述,它所说的看起来更简单,而且它根本没有谈论合并策略......

正确或最合适的方式应该是什么?非常感谢您提供有关如何管理此场景的说明和/或简单示例。

提前致谢。

【问题讨论】:

【参考方案1】:

你那里的东西看起来不错。

您正在使用私有队列来完成您的工作,并将其保存到持久存储中。

如果您只有少量更改,那么您会没事的。在这种情况下,您希望为您的上下文处理NSManagedObjectContextDidSaveNotification,并将更改合并到您的其他上下文中

[context mergeChangesFromContextDidSaveNotification:notification];

但是,如果您确实要进行大量更改,您可能需要一个单独的持久存储协调器(附加到同一个存储)。通过这样做,您可以写入存储,而另一个 PSC 上的 MOC 正在读取。如果您与其他阅读器共享 PSC,则一次只能访问一个,您可能会导致阅读器阻塞,直到您的写入完成。

此外,如果您要进行大量更改,请确保在自动释放池中小批量进行更改,并在每批后保存。看看这个类似的问题:Where should NSManagedObjectContext be created?

最后,如果您要进行大量更改,那么仅重新获取数据可能比处理所有合并更有效。在这种情况下,您不需要观察通知,也不需要进行合并。这很容易。请注意,如果您这样做,您真的应该有一个单独的 PSC...特别是如果您想以小批量保存和通知。

[privateContext performBlock: ^

    // Parse files and/or call services and parse
    // their responses

    dispatch_async(dispatch_get_main_queue(), ^
        // Refetch the data you want... if on ios, this is likely as simple
        // as telling the fetched results controller to refetch, and
        // reloading your table view (or whatever else is using the data).
    );
];

【讨论】:

谢谢!目前我没有在数据更新方面做很多改变,但这可能会在未来增加,所以我想我会采用重新获取数据而不是合并更改的方法......现在我出现了一个问题:什么创建私有上下文和像我目前正在做的那样直接使用它并将其设置为子上下文有什么区别? @AppsDev 这本身就是一个大问题。我可以在评论空间中给出的最佳答案是,我只对我的主 MOC 使用嵌套上下文(这是因为我有自己的异步获取设置,然后可以填充到主 MOC)。我把所有的储蓄都放在一个单独的 MOC 上,直接连接到它自己的 PSC。就像我上面描述的那样管理合并......如果它很小,则在保存时进行合并,如果它很大,则重新获取。 谢谢。关于创建上下文自己的 PSC ...是否还需要创建一个新的 NSPersistentStore 或者有没有办法使用我已经拥有的主线程中的一个(默认情况下在 AppDelegate 中创建的那个)? 还有一个问题……如果在performBlock: 中调用异步Web 服务会怎样?我怎么能等到我得到他们所有人的响应才能重新获取主线程中的数据? @AppsDev 我创建了一个全新的堆栈。如果您有一系列异步事件,请在它们全部完成后刷新。您只需拨打dispatch_async(dispatch_get_main_queue, BLOCK) 即可随时随地进行刷新。

以上是关于将主上下文和私有上下文与 Core Data 合并的主要内容,如果未能解决你的问题,请参考以下文章

如何通过创建本地上下文将 GCD 与 Core Data 一起使用

应用重新启动时数据不会在 Core Data 中持久化

多线程 CoreData 应用程序中主上下文和私有上下文的推荐合并策略

在 iOS 中传递上下文以将 Core Data 与 Storyboard 一起使用

NSManagedObjectContext 从私有上下文合并,只刷新改变的对象

iOS:Core Data Merge 策略如何影响 NSManagedObjectContext 保存和刷新操作