你能在NSManagedObjectContext的performBlock之外使用NSManagedObject吗?

8

为了帮助更好地处理并发,NSManagedObjectContext添加了performBlock:和performBlockAndWait:方法。我一直在使用它们,但可能相对天真,现在意识到我从未真正问过一个问题。

如果我在performBlock方法内部创建一个NSManagedObject子类,则其“home”线程是其父上下文的线程——在NSPrivateQueueConcurrencyType情况下,这可能是一个独立的线程,我无法访问其他内容。

因此,我需要执行performBlock调用才能访问我的托管对象中包含的数据吗?或者当使用getter时是否有后台魔法来帮助保护我?(尽管这似乎是个坏主意...)

2个回答

16

NSManagedObject不应在其managedObjectContext的线程/队列之外使用(有时可以工作,有时会崩溃==> 不要这样做)。

CoreData不保证安全读取对象。

要访问由“私有队列”上下文拥有的对象,请始终使用[context performBlock:...][context performBlockAndWait:...],除非您访问其objectIDmanagedObjectContext属性。


谢谢,基本上我认为这是必要的...我希望我错了。我需要重新观看WWDC视频,因为我不记得他们必须这样做...不过,我怀疑有很多WWDC视频我需要重新观看。 - RonLugge
1
我想补充一点,苹果工程师明确表示NSManagedObject的读取不是线程安全的,因为Core Data会进行缓存,而缓存写入不是线程安全的。 - George Karpenkov

9

你确实需要使用performBlock:performBlockAndWait:,但有一个例外。如果你使用NSMainQueueConcurrencyType并且在主队列上使用托管对象,则可以直接访问它,无需块。这在你需要从托管对象更新UI,反之亦然时非常方便。


1
另一个例外是 NSConfinementConcurrencyType,它类似于主队列,仅适用于特定线程(托管上下文的“旧”版本)。 - Dan Shelly
我想我应该更好地表达我的问题,因为它基本上只涉及到NSPrivateQueue和NSMainQueue类型……即便如此,主要是针对私有队列版本,这要感谢这个神奇的exception。 - RonLugge

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接