核心数据并发问题

Coredata concurrency issues

我有一个 NSOperation subclass,它有自己的私有上下文,还有一个单例数据管理器 class,它在主队列上有一个上下文。所有 UI 和 crud 操作都是由这个单例 class 完成的,而从云工具包的后台获取是由 NSOperation subclass 完成的。几乎没有疑问如下。

  1. 以下是我在 NSoperation subclass.Can 下面的代码创建死锁的代码?

    self.localStoreMOC?.performBlockAndWait({ () -> Void in
    //Long process of fetching data from cloud and pushing changes to cloud happens here. 
    
      var error:NSErrorPointer = nil
    
      if self.localStoreMOC!.hasChanges
      {
        do
        {
          try self.localStoreMOC!.save()
        }
        catch let error1 as NSError
        {
          error.memory = error1
        }
    
        if error == nil
        {
          self.localStoreMOC!.parentContext!.performBlockAndWait({
    
            do
            {
              try self.localStoreMOC!.parentContext!.save()
            }
            catch let error1 as NSError
            {
              print("wasSuccessful error1 \(error1)")
    
            }
    
          })
        }
      }
    }
    
  2. 如果我有另一个单例 class 使用这个 class NSManagedOBject 我需要通过 ID 传递它们吗?

首先,您需要在 运行 时间参数中打开 -com.apple.CoreData.ConcurrencyDebug 1。这将有助于确保您在正确的 thread/queue.

上调用所有内容

其次,您正在对可选项进行大量强制解包,这是一个非常糟糕的习惯。最好正确解包或使用可选解包。

第三,当你暂停调试器时会发生什么?它暂停的代码行在哪里?您在哪个队列中?

只需打开并发调试就很可能会显示您的问题。

项目 2

如果您想将对 NSManagedObject 的引用从一个上下文传递到另一个上下文,那么是的,您需要使用 NSManagedObjectID,因为 NSManagedObject 传递不安全上下文之间。

代码格式化

正在调整格式,您可能对结果感兴趣:

guard let local = localStoreMOC else { fatalError("Local store is nil") }
guard let parent = local.parentContext else { fatalError("Parent store is nil") }
local.performBlockAndWait {
    //Long process of fetching data from cloud and pushing changes to cloud happens here. 
    if !local.hasChanges { return }
    do {
        try local.save()
        parent.performBlockAndWait {
            do {
                try parent.save()
            } catch {
                print("wasSuccessful error1 \(error)")
            }
        }
    } catch {
        print("Failed to save local: \(error)")
    }
}

这消除了可选值的强制解包,并且如果在任何一种情况下都出现错误,则会打印出两个错误。

更新

Also, some developers, say that nested performblockandwait like above will cause deadlock.

performBlockAndWait永远不会造成死锁。它比那个更聪明。

  • 如果您要从一个队列转到另一个队列,那么您希望每个队列都像代码描述的那样阻塞并等待。
  • 如果您在正确的队列中并调用了 performBlockAndWait,那么该调用实际上是空操作,并且会 NOT 死锁