我已经研究了很多关于如何使用 NSManagedObjectContext 的文章和讨论,但仍然无法为我的项目找到令人满意的架构。
在我的应用程序中,可以从三个来源修改数据,当同时发生冲突时按优先级排序(例如,云的优先级最低):
- 用户界面,
- BLE 消息,
- 来自云端的 HTTP 响应
由于我仍然不是 iOS 开发方面的专家,因此我尽量避免为每个源使用多个上下文。然而,经过数周的反复试验,我很不情愿,但开始考虑是否真的需要采用多上下文方法。
一开始,我尝试在主上下文上使用 context.perform { } 来做所有的数据更改操作(add/update/delete,除了获取)。我将 fetch 保持为同步功能,因为我希望数据获取是即时的,以便可以响应 UI。但是,在这种方法下,我偶尔会收到 "Collection <__NSCFSet: 0x000000000> was mutated while being enumerated" 异常(我想这可能发生在 forEach 或 map 函数用于批量数据处理)。我还发现,当后台队列中有大量记录要更新时,这种方法仍然会阻塞 UI。
因此,我创建了一个后台上下文并使用父子模型来操作数据。基本上主上下文(父)只负责获取数据,而后台上下文(子)通过 backgroundContext.perform { }< 操作所有数据更改(添加/更新/删除)/ 。这种方法解决了 UI 阻塞问题,但是偶尔会出现 collection mutated 错误,并且在这种结构下还会出现另一个问题:例如,当我在 ViewController A 中添加一条数据记录并移动到 View Controller B 时,应用程序会崩溃,这即使后台上下文尚未完成添加数据记录,也会立即获取相同的数据。
因此,我想就我的项目中使用 Core Data 提出一些建议。在我的父子数据上下文模型下我做错了什么吗?或者,我应该不可避免地选择一个没有父子的真正的多上下文模型吗?怎么做?
我的主要上下文(父)和背景上下文(子)是这样启动的:
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)
}
}
}
任何关于核心数据结构的建议都将不胜感激。
Best Answer-推荐答案 strong>
您是否探索过使用 NSFetchedResultsController 来获取数据?
NSFetchedResultsController 提供了一种线程安全的方式来观察由于 CoreData 中的创建、更新或删除操作而导致的数据变化。
使用 NSFetchedResultsController 的委托(delegate)方法来更新 UI。
理想情况下,controllerDidChangeContent 委托(delegate)会给你一个更新 UI 的指示。 Documentation for reference
关于ios - 在后台同步的同时在 UI 交互上操作 Core Data Context 的最佳实践,我们在Stack Overflow上找到一个类似的问题:
https://stackoverflow.com/questions/47027771/
|