Coredata 并发问题
Posted
技术标签:
【中文标题】Coredata 并发问题【英文标题】:Coredata concurrency issues 【发布时间】:2016-05-10 14:36:30 【问题描述】:我有一个具有私有上下文的 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 传递它们?
【问题讨论】:
【参考方案1】:首先,您需要在运行时参数中打开-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
,那么该调用实际上是无操作的,并且将不会死锁
【讨论】:
谢谢马库斯,嵌套的 performblockandwait 会造成死锁问题吗?有人说使用嵌套的 performblockandwait 不好? 1.打开运行时并发变量,虽然我知道帮助同步的单例类正在另一个线程上使用托管对象,但它们不在主线程上,但调试变量仍然存在问题。 2. 感谢 marcus 的代码格式化,并将使用 optional 的正确解包。 3. 还有一些开发者说像上面这样嵌套的 performblockandwait 会导致死锁。以上是关于Coredata 并发问题的主要内容,如果未能解决你的问题,请参考以下文章