这是关于核心数据和多线程的另一个问题:
我正在iPhone上编写一个应用程序,它从Internet检索XML数据,在后台线程中解析它(使用NSXMLparser),并使用自己的NSManagedObjectContext将数据保存在Core Data中。我有一个类 - 让我们称之为DataRetriever - 这样做对我来说。
然后有不同的UIViewControllers检索数据以在各自的UITableViews中显示它,当然这在主线程上使用NSFetchedResultsControllers和用于读取的单个托管对象上下文发生。
我已经阅读了this question的答案,它告诉我需要在后台线程上注册NSManagedObjectDidSaveNotifications(这将由我想的DataRetriever类完成),然后调用mergeChangesFromContextDidSaveNotification方法。在主线程上从该类读取上下文。我认为,这完全是线程不安全的。不过,我可能会以错误的方式解释这一点。
我还阅读了有关该主题的Apple文档的this part(使用通知的其他线程中的跟踪更改),它告诉我只需注册来自的NSManagedObjectDidSaveNotifications 在主线程上的视图控制器中读取上下文然后它必须调用mergeChangesFromContextDidSaveNotification来更新其读取上下文。
我选择了Apple的建议:我现在让我的视图控制器使用读取托管对象上下文作为通知源,在主线程上注册NSManagedObjectDidSaveNotifications。在写入上下文中执行此操作可能不是线程安全的,Apple的文档对此并不十分具体。
结果:没有崩溃,但我也没有收到任何通知。
旁注:我在Apple的文档中读到,通知不会自动传播到其他线程,我甚至可能会从错误的上下文中侦听通知,但为什么Apple会告诉我这样做呢?
非常感谢任何帮助。
- 编辑 -
为了清楚起见,我正在注册来自特定 NSManagedObjectContext的通知,Apple的文档特别声明(here)某些系统框架可能会使用Core Data本身的实例,如果我没有指定源,我可能会收到与我无关的上下文的通知。我之前提到的文档没有说明这一点。欢迎任何关于此设计选择的评论。
答案 0 :(得分:1)
UI在主线程上运行,因此您需要任何可能在另一个线程上完成UI操作的密集处理。您有主线程中的上下文侦听通知,因为主线程上下文通常是唯一需要更新自己的上下文,因为其他线程中的其他上下文的更改。
所有这些都是线程安全的,因为只要一个或多个上下文仍在使用数据,就不会从持久存储中删除数据。因此,如果上下文A具有包含数据的对象,而上下文B删除表示相同数据的另一个对象,则上下文A中的对象保持活动状态,直到上下文A调用合并。
基本上,每个上下文都在自己的小世界中运行,直到你调用merge。 Core Data不会出现通常困扰基于线程的数据操作的竞争条件。