2012-06-25 5 views
1

Так что я знаю, что NSManagedObjects не являются потокобезопасными, и лучший способ получить объекты из фонового потока - использовать [context objectWithId:id]; и, таким образом, передавать идентификаторы объектов вместо фактического объекта.Доступ к NSManagedObject из фонового потока

Скажем, у меня есть в моем AppDelegate глобальную NSManagedObject (не лучший шаблон дизайна, но только для примера) NSManagedObject *myObject;

Безопасно для доступа этого объекта objectId из фонового потока? Как это:

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

ответ

2

Это не безопасно, так как нет никакой гарантии, что вызов objectID на myObject является безопасным. Вы должны получить доступ к объекту ID за пределами своего блока (например, в основном потоке), а затем использовать его в своем блоке. Что-то вроде:

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

Я согласен с вашим решением, но мне нужно понять что-то, objectID для NSManagedObject является неизменяемым свойством (после первого сохранения). разве безопасно ли доступ к неизменяемому свойству из любого потока? – PushpRaj

+1

@PushpRaj В целом, свойство быть неизменным не гарантирует безопасность потока. Для NSManagedObject документация достаточно ясна, что вы не должны передавать NSManagedObjects из одного потока в другой, что и делает код примера (независимо от того, какие свойства вы хотите получить). Вы правы, что детали реализации * вероятно * означают, что безопасно получить доступ к объекту ID из фонового потока, но это, безусловно, не гарантируется. –

1

Для каждого потока, который вы используете (исторически), необходимо иметь отдельный контекст. Поскольку dispatch_async не гарантируется для запуска в любом потоке, вам нужно будет создать контекст внутри блока. В качестве альтернативы, на iOS 5.0 или выше, NSManagedContext поставляется с новыми режимами параллелизма. Контекст создаст собственную приватную очередь для передачи блоков. Если вам нужно поддерживать iOS 4.x, вы можете моделировать после этого поведения. Создайте последовательную очередь и получите доступ только к контексту из этой очереди.

Вы не можете делать ничего, что вызывает запрос или изменение в контексте из двух разных потоков, поскольку оно может создать условие гонки.