从后台线程访问NSManagedObject

所以我知道NSManagedObjects不是线程安全的,从后台线程获取对象的最好方法是使用[context objectWithId:id]; ,所以传递对象id而不是实际对象。

假设我的AppDelegate有一个全局NSManagedObject (不是最好的设计模式,只是例如) NSManagedObject *myObject;

从后台线程访问此对象的objectId是否安全? 喜欢这个:

 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{ objectId = appDelegate.myObject.objectId; //is this thread safe? } 

这是不安全的,因为无法保证在myObject上调用objectID是安全的。 您应该访问块外部的objectID(例如,在主线程上),然后在块中使用它。 就像是:

 NSManagedObjectID *objectID = appDelegate.myObject.objectId; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{ // use objectID here. } 

您需要为您使用的每个线程(历史上)设置单独的上下文。 由于无法保证dispatch_async在任何给定线程上运行,因此您需要在块内创建上下文。 或者,在iOS 5.0或更高版本上,NSManagedContext带有新的并发模式。 上下文将创建自己的专用串行队列,以便您将块传递给。 如果您需要支持iOS 4.x,那么您可以在此行为后进行建模。 创建一个串行队列,只访问该队列中的上下文。

您可能不会执行任何导致查询或从两个不同线程更改上下文的操作,因为它可能会创建竞争条件。