我正在寻找在后台更新相当大的基于核心数据的数据集的最佳方法,同时对应用程序 UI(主线程)的影响尽可能小。
关于这个主题有一些很好的材料,包括:
- WWDC 2013 的第 211 场会议(核心数据性能优化和调试,从大约 25:30 开始)
- 从 objc.io 导入大型数据集
- 来自 objc.io的常见后台实践(后台核心数据)
- 具有嵌套托管对象上下文的后台
根据我的研究和个人经验,最好的选择是有效地使用两个单独的核心数据堆栈,它们只在数据库 (SQLite) 级别共享数据。这意味着我们需要两个独立NSPersistentStoreCoordinators
的,每个都有自己的NSManagedObjectContext
。在数据库上启用预写日志记录(从 iOS 7 开始默认),几乎所有情况下都可以避免锁定需求(除非我们有两个或更多同时写入,这在我的场景中不太可能)。
为了进行高效的后台更新和节省内存,还需要批量处理数据并定期保存后台上下文,以便将脏对象存储到数据库中并从内存中刷新。可以使用此时NSManagedObjectContextDidSaveNotification
生成的 将背景更改合并到主上下文中,但通常您不希望在保存批次后立即更新 UI。您希望等到后台作业完全完成后再刷新 UI(在 WWDC 会话和 objc.io 文章中都推荐)。这实际上意味着应用程序主上下文在一段时间内与数据库保持不同步。
所有这一切都引出了我的主要问题,即,如果我以这种方式更改数据库,而不立即告诉主要上下文合并更改,会出现什么问题?我假设这不是所有的阳光和玫瑰。
我脑海中的一个特定场景是,如果需要为在主上下文中加载的对象执行故障,如果后台操作介于两者之间从数据库中删除了该对象,会发生什么?例如,这是否会发生在基于 NSFetchedResultsController 的表视图上,该表视图使用 batchSize 以增量方式将对象提取到内存中?即,尚未完全获取的对象被删除,但我们向上滚动到需要加载对象的点。这是一个潜在的问题吗?其他事情会出错吗?我将不胜感激有关此事的任何意见。