[我在一些地方读过(例如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,而必须使用自己的代码来设置核心数据堆栈?
2)鉴于NSPersistentContainer是新的API,我认为它必须具有某种方式来实现相同的效果(将托管对象更改保存在后台线程中)。我不知道这是什么我正在考虑以下方法,其中save()仅在保存上下文中而不是在主上下文中调用。但这更复杂,而且不如上面的自然。有没有更简单的方法?
Persistent Store Coordinator
↑ ↑
Context (main) --merge--> Context (saving)
↑
Context (editing)
UPDATE:再三考虑,这种方法行不通,因为合并基于通知。如果在主上下文中未调用save(),则不会触发任何通知。
嗯,我想知道是否可以创建另一个mainQueueConcurrencyType的NSManagedObjectContext,将其设置为我最初想要的,然后用它替换由NSPersistentContainer创建的那个吗?
谢谢您的建议。
我想我可能找到一种解决方案:
persistent store coordinator
↑ ↑
main context private context (edit, fetch, etc.)
automaticallyMergesChangesFromParent
设置为true来完成此操作。这意味着每次在私有上下文中编辑托管对象时,都应立即调用一次save()调用。
我认为,有一种情况是,用户在调用save()调用时会挂起应用程序,这可能导致在从屏幕上删除视图时更新主上下文。但是我认为即使没有Core Data多线程也可能发生这种情况,因此我认为UIKit应该能够正确处理这种情况。