从后台线程访问NSManagedObject

时间:2012-06-25 00:49:39

标签: iphone objective-c ios cocoa core-data

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

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

从后台线程访问此对象的objectId是否安全?像这样:

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

2 个答案:

答案 0 :(得分:3)

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

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

答案 1 :(得分:1)

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

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