【问题标题】:NSManagedObjectContext.performAndWait{} cause a crashNSManagedObjectContext.performAndWait{} 导致崩溃
【发布时间】:2020-12-02 02:13:45
【问题描述】:

我不确定我在这里做错了什么,但由于这个原因,我的应用程序崩溃了。这是我在 AppDelegate 中的 coredata 堆栈,如下所示。

lazy var viewContext: NSManagedObjectContext = {
return self.persistentContainer.viewContext
}()

lazy var cacheContext: NSManagedObjectContext = {
return self.persistentContainer.newBackgroundContext()
}()

lazy var updateContext: NSManagedObjectContext = {
let _updateContext = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
_updateContext.parent = self.viewContext
return _updateContext
}()

然后我创建了一个 Singleton 类来管理我的 CoreData 操作,如下所示。

class StorageManager:NSObject {

  private override init() {}

  private static var SMInstance: StorageManager?

  public static var shared : StorageManager {
    if SMInstance == nil {
      SMInstance = StorageManager()
    }

    return SMInstance!
  }



//Represent a single context for all the operations with lazy loading
lazy var managedObjectContext : NSManagedObjectContext = {
      let appDelegate = UIApplication.shared.delegate as! AppDelegate
      appDelegate.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
      return appDelegate.viewContext
}()


lazy var privateMOC : NSManagedObjectContext = {
         let appDelegate = UIApplication.shared.delegate as! AppDelegate
         return appDelegate.updateContext
}()


 private func synchronize() {
  do {

    try self.privateMOC.save() 

      self.managedObjectContext.performAndWait {
          do {
            try self.managedObjectContext.save()

            print("Saved to main context")
          } catch {
            print("Could not synchonize data. \(error), \(error.localizedDescription)")
          }

      }
  } catch {
    print("Could not synchonize data. \(error), \(error.localizedDescription)")
  }

 }

}

将数据保存在同一类中的示例保存方法编写如下。但这有时会给我这个错误

*** 由于未捕获的异常“NSGenericException”而终止应用程序, 原因:'*** 集合 <__nscfset:> 在发生突变时 正在枚举中...

func savedata() {     

  DispatchQueue.main.async(execute: {

   let entity = User(context: self.privateMOC)
       
     entity.name = "JOHN PAUL"
        
    //IT crash here
     self.privateMOC.performAndWait {
          self.synchronize()
      }

  })

}

【问题讨论】:

  • 你已经问过这个问题here。请不要重复发布相同的问题。

标签: ios swift core-data swift5 nsmanagedobjectcontext


【解决方案1】:

这个错误可能是因为您在后台上下文中创建User实体,但在主线程上执行操作。

删除DispatchQueue.main.async

有关 Core Data 和线程的更多信息,请阅读here

编辑:在私有/后台上下文中创建对象/实体应该是这样的:

let privateMOC = self.privateMOC
privateMOC.performAndWait {
     let entity = User(context: privateMOC)
     entity.name = "JOHN PAUL"
     self.synchronize(privateMOC: privateMOC)
} 

还有同步功能应该是这样的:

private func synchronize(privateMOC: NSManagedObjectContext) {
  do {

    try privateMOC.save() 

      DispatchQueue.main.async {
          self.managedObjectContext.performAndWait {
          do {
            try self.managedObjectContext.save()

            print("Saved to main context")
          } catch {
            print("Could not synchonize data. \(error), \ (error.localizedDescription)")
          }

      }
    }
  } catch {
    print("Could not synchonize data. \(error), \(error.localizedDescription)")
  }

 }

【讨论】:

  • 我无法删除 DispatchQueue.main.async,如果我这样做,它会在惰性 var viewContext 中给我错误:NSManagedObjectContext = { return self.persistentContainer.viewContext }()
  • 如果你这样做,它会给你一个明显的错误“UIApplication.delegate must be used only from main thread”
  • 我编辑了我的答案,如果您花时间思考为什么会发生这种情况而不是投反对票,您就会明白这一点。 :)
  • 这仍然会导致间歇性崩溃,我只是想知道这可能是因为同步方法
  • 当然可以,是多线程环境导致这样的崩溃。
猜你喜欢
  • 2018-01-23
  • 2013-11-11
  • 2011-01-24
  • 2015-02-23
  • 2011-04-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多