我有一个NSOperation子类,它有私有上下文,以及一个在主队列上有上下文的单例数据管理器类。所有的UI和crud操作都是由这个单例类完成的,云套件的后台提取是由NSOperation子类完成的。几乎没有疑问如下。
以下是我在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)")
}
})
}
}
}
如果我有另一个使用此类NSManagedOBject的单例类,我是否需要通过ID传递它们?
答案 0 :(得分:0)
首先,您需要在运行时参数中打开-com.apple.CoreData.ConcurrencyDebug 1
。这将有助于确保您在正确的线程/队列上调用所有内容。
其次,你正在做很多强制解包的选项,这是一个非常糟糕的习惯。最好正确打开它们或使用可选的展开。
第三,暂停调试器时会发生什么?它正在暂停的代码行在哪里以及你在哪个队列?
打开并发调试很可能会向您展示您的问题。
如果您想要将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
,则该呼叫实际上将成为无操作,并且不死锁