【问题标题】:Save managed object changes in background with NSPersistentContainer使用 NSPersistentContainer 在后台保存托管对象更改
【发布时间】:2020-04-26 01:51:28
【问题描述】:

我在一些地方(例如 a high score answer here)读到,将主托管上下文作为后台托管上下文的子级以节省 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 并且必须使用自己的代码设置 Core Data 堆栈?

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

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

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

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

感谢您的任何建议。

【问题讨论】:

    标签: ios core-data nsmanagedobjectcontext nspersistentcontainer


    【解决方案1】:

    我想我可能找到了解决办法:

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-11-14
      • 1970-01-01
      • 1970-01-01
      • 2018-03-27
      • 2020-07-05
      • 1970-01-01
      • 2018-09-02
      • 1970-01-01
      相关资源
      最近更新 更多