【问题标题】:Multiple context trouble. Can't make two queues (main and private) save data in Core Data多上下文麻烦。无法在 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()
    }

我做错了什么?

【问题讨论】:

    标签: swift core-data queue nsmanagedobjectcontext


    【解决方案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)")
                  }
              }
          }
      

      我从 ma​​nagedContext.performAndWait() 块中推迟了 privateContext.perform()。 此外,我将 CoreDataManager.instance.persistentContainer.viewContext 更改为 CoreDataManager.instance.managedContext 这是我的上下文(惰性变量) 它有效! :)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-01-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-10-08
        • 2012-10-08
        • 1970-01-01
        • 2022-06-10
        相关资源
        最近更新 更多