Нужно ли делать чтение основных данных в режиме выполнения при использовании NSMainQueueConcurrencyType?

По словам Даниэля Эггерт, ответьте на этот вопрос, при использовании контекста управляемого объекта с NSPrivateQueueConcurrencyType необходимо сделать все, что касается его или объектов, принадлежащих ему в пределах performBlock: или performBlockAndWait:

То же самое верно для NSMainQueueConcurrencyType? Представьте себе следующий код, запущенный в основном потоке, например, в UIViewController:

self.moc = [[[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType] autorelease];
//moc setup

__block RHWidget *widget = nil;

[self.moc performBlockAndWait:^{
    widget = [(RHWidget *)[self.moc objectWithID:self.widgetObjectID] retain];
}];

self.labelView.text = widget.descriptionString;

[widget release];

Можно ли использовать виджет вне блока, так как мы знаем, что мы находимся в основном потоке? Или это необходимо сделать:

__block NSString *description = nil;

[self.moc performBlockAndWait:^{
    RHWidget *widget = (RHWidget *)[self.moc objectWithID:self.widgetObjectID];
    description = [widget.descriptionString copy];
}];

self.labelView.text = description;

[description release];

Что-то изменится, если там есть другой NSManagedObjectContext, возможно, тип частной очереди, работая в блоках и нажав изменения до self.moc как parentContext?

Это, конечно, немного надуманный пример, но было бы неплохо безопасно передать этот виджет, например, для модального контроллера представлений, которому необходимо получить доступ к некоторым свойствам виджета. Должен ли я передавать идентификатор объекта widget вместо этого и повторять его в performBlock: в новом контроллере представления?

Ответ 1

Обновление: Согласно WWDC 2011 Сессия 303 (что нового в основных данных на iOS), NSMainQueueConcurrencyType предназначена для нормального обмен сообщениями по основной теме; вам нужно использовать -performBlock: при взаимодействии с контекстом из другого потока. (Все еще важные части моего первоначального ответа ниже.)


Я сделал приложение или два, которые изменяют шаблон приложения "Мастер-Детс" по умолчанию для Xcode, чтобы сделать основной "MOC" (созданный делегатом приложения и переданный между контроллерами представлений) только для основной очереди и родительский контекст частной очереди, который я использую для фоновых операций, таких как импорт данных из веб-выборки. Таким образом, большинство применений контекста и его объектов происходит без обертывания в performBlock:. (Единственный раз, когда я использую performBlock:, - это переместить изменения из контекста фоновой задачи обратно в основной, чтобы обновить пользовательский интерфейс.) Работает нормально.