Coredata并发问题

时间:2016-05-10 14:36:30

标签: ios objective-c multithreading core-data deadlock

我有一个NSOperation子类,它有私有上下文,以及一个在主队列上有上下文的单例数据管理器类。所有的UI和crud操作都是由这个单例类完成的,云套件的后台提取是由NSOperation子类完成的。几乎没有疑问如下。

  1. 以下是我在NSoperation子类中的代码。下面的代码可以创建死锁吗?

    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. 如果我有另一个使用此类NSManagedOBject的单例类,我是否需要通过ID传递它们?

1 个答案:

答案 0 :(得分:0)

首先,您需要在运行时参数中打开-com.apple.CoreData.ConcurrencyDebug 1。这将有助于确保您在正确的线程/队列上调用所有内容。

其次,你正在做很多强制解包的选项,这是一个非常糟糕的习惯。最好正确打开它们或使用可选的展开。

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

打开并发调试很可能会向您展示您的问题。

第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)")
    }
}

这将删除强制解包选项并在两种情况下都输出错误时打印出错误。

更新

  

此外,一些开发人员说,嵌套performblockandwait如上所述将导致死锁。

performBlockAndWait永远不会导致死锁。它比那更聪明。

  • 如果您要从一个队列转到另一个队列,那么您希望每个队列都像代码描述的那样阻塞并等待。
  • 如果您在正确的队列中并且呼叫performBlockAndWait,则该呼叫实际上将成为无操作,并且死锁