在我的应用程序中,我有一个NSFetchResultController
来加载UITableView中的Core Data对象。
与此FRC关联的提取请求使用viewContext
(iOS10)可用的新NSPersistentContainer
属性。
当我选择一个单元格时,我将Core Data对象传递给一个新的ViewController。这个新的VC仍然使用viewContext。
从这个ViewController,我可以从模态呈现的ViewControllers更新Core Data对象。为此,我使用newBackgroundContext()
作为模态ViewControllers。我可以毫无问题地保存更新Core Data对象。
问题是FRC不会使用后台上下文中的更新Core Data对象自动更新。 就好像viewContext没有被接收并处理Core Data对象更新。
如果我为viewContext(app wide)将automaticallyMergesChangesFromParent
设置为true,则在保存背景上下文时FRC会获取更新的Core Data对象。根据我的理解,viewContext应该自动管理数据的合并。该文档描述了viewContext:"该上下文被配置为世代的并自动使用来自其他上下文的保存通知。"
您能否阐明如何使用NSFetchResultController处理不同的上下文?
答案 0 :(得分:30)
你看到了正确的行为。如果您希望viewContext自动从其他上下文中获取更改,包括newBackgroundContext()
创建的更改,则必须将automaticallyMergesChangesFromParent
设置为true
。
我同意文档在这一点上令人困惑,“...并自动使用来自其他上下文的保存通知。”
答案 1 :(得分:8)
自动将来自父需求的更改合并到viewContext上,如下所示:
persistentContainer.viewContext.automaticallyMergesChangesFromParent = true
答案 2 :(得分:6)
我还没有直接遇到这个问题,但是如果newBackgroundContext实际上是在viewContext下分层的,那么你的问题就像奇怪一样,因为来自新上下文的任何保存只会更新viewContext,这也是必须要做的它自己保存以获取持久存储的更改(您说这是正确发生的)。基于这种怀疑,我查看了Apple所说的开发人员文档:
调用此方法(newBackgroundContext())会导致持久容器创建并返回一个新的NSManagedObjectContext,并将concurrencyType设置为privateQueueConcurrencyType。此新上下文将直接与NSPersistentStoreCoordinator关联,并设置为自动使用NSManagedObjectContextDidSave广播。
因此,它不会与viewContext处于父子关系中。根据指导,似乎新的上下文将被旧的通知更改,反之亦然,因此当新的上下文发生更改时,您必须对viewContext进行刷新,如果新的上下文发生更改,您可以以编程方式执行您可以在代码中跟踪它,也可以使用NSManagedObjectsContext中的某个更改通知来触发操作。
答案 3 :(得分:0)
不适用于我,所以我将保存块从更改为
self.persistentContainer.performBackgroundTask { (context) ... }
到
self.persistentContainer.newBackgroundContext().performAndWait { ... }
并且要正确地设置automaticallyMergesChangesFromParent
为使自动合并起作用。
lazy var viewContext: NSManagedObjectContext = {
self.persistentContainer.viewContext.automaticallyMergesChangesFromParent = true
self.presistentContainer.viewContext.mergePolicy = NSMergePolicy.mergeByPropertyObjectTrump
return self.persistentContainer.viewContext
}()
我不知道为什么context
中的performBackgroundTask
没有合并到viewContext
。