0

我在一些地方(比如这里的高分答案)读到,将主托管上下文作为后台托管上下文的子级以节省 save() 时间并提高 UI 响应能力是一种很好的做法。

Persistent Store Coordinator
            ↑
Managed Object Context (for saving)       <= note this
            ↑
Managed Object Context (main)
            ↑
Managed Object Context (for editing)

但问题是,由 iOS 模板代码创建的主要托管上下文与 Persistent Store Coordinator 相关联,并且似乎没有支持的方式来改变它。我尝试了以下代码:

lazy var persistentContainer: NSPersistentContainer = {
    // Template code: create persistent container
    // ...

    // My code
    let saveMOC = container.newBackgroundContext()
    container.viewContext.persistentStoreCoordinator = nil
    container.viewContext.parent = saveMOC

    return container
}()

但得到了一个 NSException:

uncaught exception 'NSInternalInconsistencyException', reason: 'Context already has a coordinator;  cannot replace.'

我的问题是:

1)这是否意味着,要实现上述架构,我不能使用 NSPersistentContainer 并且必须使用我自己的代码设置核心数据堆栈?

2)鉴于 NSPersistentContainer 是新的 API,我认为它必须有一些方法来达到相同的效果(在后台线程中保存托管对象的更改)。我想知道它是什么?我正在考虑以下方法,其中 save() 仅在保存上下文中调用,而不是在主上下文中调用。但它更复杂,不像上面的那样自然。有没有更简单的方法?

          Persistent Store Coordinator
            ↑                      ↑
    Context (main)  --merge-->  Context (saving)
            ↑
    Context (editing)

更新:再想一想,这种方法不起作用,因为合并是基于通知的。如果在主上下文中未调用 save(),则不会触发任何通知。

嗯,我想知道是否可以创建另一个 mainQueueConcurrencyType 的 NSManagedObjectContext,按照我最初的意愿进行设置,然后用它替换 NSPersistentContainer 创建的那个?

感谢您的任何建议。

4

1 回答 1

0

我想我可能会找到一个解决方案:

    persistent store coordinator
      ↑                      ↑
main context          private context (edit, fetch, etc.)
  • 所有编辑都在私人环境中完成
  • 主上下文不会更改托管对象,而只是从持久存储协调器获取更新。它通过设置automaticallyMergesChangesFromParent为 true 来做到这一点。

这意味着每次在私有上下文中编辑托管对象时,都应立即调用 save() 调用。

我认为,一种极端情况是用户在调用 save() 调用时暂停了应用程序,这可能会在视图从屏幕上删除时导致主上下文更新视图。但我认为即使没有 Core Data 多线程也可能发生这种情况,所以我认为 UIKit 应该能够正确处理这种情况。

于 2020-01-09T11:13:26.333 回答