多上下文麻烦。无法在 Core Data 中创建两个队列(主队列和私有队列)保存数据
Posted
技术标签:
【中文标题】多上下文麻烦。无法在 Core Data 中创建两个队列(主队列和私有队列)保存数据【英文标题】:Multiple context trouble. Can't make two queues (main and private) save data in Core Data 【发布时间】:2019-06-21 17:45:07 【问题描述】:我想在 ManagedObjectContext 的私有队列上设置保存数据,但无法正确执行。
我已经在 mainThread 中使用一个上下文保存了数据,它工作正常。但是当我添加 .perform() 和 performAndWait() 函数后,我无法在 SQLite 中获取我的数据。
我在 CoreDataManager.swift 文件中有这个功能:
func saveContext()
privateObjectContext.perform
do
try self.privateObjectContext.save()
self.mainObjectContext.performAndWait
do
try self.mainObjectContext.save()
catch
fatalError("Failure to save context: \(error)")
catch
fatalError("Failure to save context: \(error)")
并从 Repository.swift 文件中调用此函数:
func insertQuestProgress(qp: QuestProgress)
//here's my code
CoreDataManager.instance.saveContext()
同样在 CoreDataManager.swift 文件中,我初始化了 privateContext 和 mainContext 的变量,就像在关于这个主题的大量文章中一样:
private lazy var privateObjectContext: NSManagedObjectContext =
var managedObjectContext = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
managedObjectContext.parent = self.mainObjectContext
return managedObjectContext
()
private lazy var mainObjectContext: NSManagedObjectContext =
var managedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
managedObjectContext.persistentStoreCoordinator = CoreDataManager.instance.persistentContainer.persistentStoreCoordinator
return managedObjectContext
()
也许它不保存,因为在 insertQuestProgress(qp: QuestProgress) 我创建了具有 CoreDataManager.instance.persistentContainer.viewContext
上下文的新实体func deleteQuestProgress(id: String)
let questProgresses = CoreDataManager.instance.fetchQuestprogress()
guard let questProgress = questProgresses.first(where: $0.questId == id) else return
CoreDataManager.instance.persistentContainer.viewContext.delete(questProgress)
CoreDataManager.instance.saveContext()
func insertQuestProgress(qp: QuestProgress)
if let quest = getQuestProgressEntityById(id: qp.questId)
quest.qpJson = converter.toJson(value: qp)
else
let questProgress = QuestProgressEntity(context: CoreDataManager.instance.persistentContainer.viewContext)
questProgress.questId = qp.questId
questProgress.qpJson = converter.toJson(value: qp)
CoreDataManager.instance.saveContext()
我做错了什么?
【问题讨论】:
【参考方案1】:乍一看,您的上下文似乎倒退了。您的主要对象上下文应该是您异步保存的对象,而私有队列上的私有上下文应该同步保存。试试这样的:
// Parent context, will save things on a private queue synchronously.
private lazy var privateContext: NSManagedObjectContext =
let moc = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
moc.persistentStoreCoordinator = coordinator
return moc
()
// Child context, should be used asynchronously.
private(set) lazy var managedContext: NSManagedObjectContext =
let moc = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
moc.parent = privateContext
return moc
()
func saveContext()
mainObjectContext.perform
do
try self.mainObjectContext.save()
self.privateObjectContext.performAndWait
do
try self.privateObjectContext.save()
catch
print("Failure to save context: \(error)")
catch
print("Failure to save context: \(error)")
这可能不是您的确切问题,但如果您仍然遇到问题,您可能需要发布更多代码:确切地 what 内容是您保存。
(另外,如果您的保存失败,请考虑不要抛出 fatalError()
。崩溃您的应用并不是很好的用户体验 - 最好通知用户和/或重试保存。)
【讨论】:
【参考方案2】:这很简单。 CoreDataManager.swift 文件中的函数 saveContext():
func saveContext()
managedContext.performAndWait
do
try self.managedContext.save()
catch
print("Failure to save context: \(error)")
privateContext.perform
do
try self.privateContext.save()
catch
print("Failure to save context: \(error)")
我从 managedContext.performAndWait() 块中推迟了 privateContext.perform()。 此外,我将 CoreDataManager.instance.persistentContainer.viewContext 更改为 CoreDataManager.instance.managedContext 这是我的上下文(惰性变量) 它有效! :)
【讨论】:
以上是关于多上下文麻烦。无法在 Core Data 中创建两个队列(主队列和私有队列)保存数据的主要内容,如果未能解决你的问题,请参考以下文章