我已经在很多关于如何使用NSManagedObjectContext
的文章和讨论中做过研究,但仍然无法为我的项目找到令人满意的架构。
在我的应用程序中,有三个来源可以修改数据,在同时发生冲突时按优先顺序排序(例如,云的优先级最低):
由于我还不是iOS开发方面的专家,我试图避免为每个源使用多个上下文。然而,经过数周的反复试验,我不情愿但是开始考虑是否真的需要采用多上下文方法。
一开始,我尝试在主要上下文中使用context.perform { }
来执行所有数据更改操作(添加/更新/删除,但 fetch )。我保持fetch是一个同步功能,因为我希望数据提取是即时的,以便能够响应UI。但是,根据这种方法,我偶尔会收到"Collection <__NSCFSet: 0x000000000> was mutated while being enumerated"
异常(我认为可能会在forEach
或map
函数中进行批处理数据处理。我还发现,当有大量记录要在后台队列中更新时,这种方法仍会阻止UI。
因此,我创建了一个背景上下文并使用父子模型来操作数据。基本上,主要上下文(父)仅负责获取数据,而后台上下文(子)通过backgroundContext.perform { }
操纵所有数据更改(添加/更新/删除)。这种方法解决了UI块问题,但是集合变异错误偶尔也会发生,并且在这种结构下会出现另一个问题:例如,当我在ViewController A中添加数据记录时,应用程序会崩溃,并移动到View Controller B,即使后台上下文尚未完成添加数据记录,也会立即获取相同的数据。
因此,我想就我的项目中的核心数据用法提出一些建议。在我的父子数据上下文模型下,我做错了吗?或者,如果没有亲子,我是否应该不可避免地选择真正的多上下文模型?怎么做?
我的主要上下文(父级)和后台上下文(子级)的启动方式如下:
lazy var _context: NSManagedObjectContext = {
return (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
}()
lazy var _backgroundContext: NSManagedObjectContext = {
let ctx = NSManagedObjectContext(concurrencyType: NSManagedObjectContextConcurrencyType.privateQueueConcurrencyType)
ctx.parent = self._context
return ctx
}()
合并功能如下:
@objc func contextDidSaveContext(notification: NSNotification) {
let sender = notification.object as! NSManagedObjectContext
if sender === self._context {
NSLog("******** Saved main Context in this thread")
self._backgroundContext.perform {
self._backgroundContext.mergeChanges(fromContextDidSave: notification as Notification)
}
} else if sender === self._backgroundContext {
NSLog("******** Saved background Context in this thread")
self._context.perform {
self._context.mergeChanges(fromContextDidSave: notification as Notification)
}
}
else {
NSLog("******** Saved Context in other thread")
self._context.perform {
self._context.mergeChanges(fromContextDidSave: notification as Notification)
}
self._backgroundContext.perform {
self._backgroundContext.mergeChanges(fromContextDidSave: notification as Notification)
}
}
}
对核心数据结构的任何建议都表示赞赏。
答案 0 :(得分:0)
您是否曾探索过使用NSFetchedResultsController来获取数据?
NSFetchedResultsController提供了一种线程安全的方法来观察由于CoreData中的创建,更新或删除操作而导致的数据更改。
使用NSFetchedResultsController的委托方法更新UI。
理想情况下,controllerDidChangeContent
委托会给您一个更新UI的指示。 Documentation for reference