2014-01-13 3 views
1

В настоящее время я изучаю, как использовать основные данные в многопоточной среде;Сохранение NSManagedObjectContext с NSPrivateQueueConcurrencyType

поэтому я создал небольшой проект с двумя NSManagedObjectContext: Главный NSManagedObjectContext с NSMainQueueConcurrencyType для чтения и его ребенок NSManagedObjectContext с NSPrivateQueueConcurrencyType для создания/обновления/удаления.

Он часто говорил, что экономя NSManagedObjectContext с NSPrivateQueueConcurrencyType должно быть сделано через performBlock: так:

[context performBlock:^ 
{ 
    Book *mutableBook = [self getMutableVersionOfBook:book]; 

    [context deleteObject:mutableBook]; 

    [context save:nil]; 
}]; 

Что произойдет, если performBlock: опускается, например:

Book *mutableBook = [self getMutableVersionOfBook:book]; 

[context deleteObject:mutableBook]; 

[context save:nil]; 

ли сохранить, а затем произойти в потоке, вызванном сохранением? Что может случиться, если performBlock: не используется?

+0

Что случится, если вы попробуете? – Abizern

+0

@Abizem сохраняет данные; Мне в основном интересно, каким образом данные сохраняются и почему это не рекомендуется. – MrJre

+0

положите точку останова перед BooL * строка mutableBook и после строки deleteObject и посмотрите, создан ли новый поток (Xcode -> Left Side-> 6th tab-> click CPU-> см. Ниже потоки.вы узнаете, происходит ли это в newthread или нет. – santhu

ответ

4

Частная очередь MOC должна касаться только -performBlock: или -performBlockAndWait:. Если вы коснетесь его каким-либо другим способом, вы нарушаете правило границ потоков данных Core, и в конечном итоге вы повредите повреждение данных.

В некоторых ситуациях это может привести к сбою в приложении, поскольку нарушение этой границы потока является ошибкой уровня приложения. Apple несколько раз отключилась от этого сбоя, и это может быть или не быть аварийным состоянием прямо сейчас. По-моему, Должно быть состояние сбоя все время.

Как правило, я рекомендую использовать потоковые ограниченные MOC как дочерние элементы основного MOC, а не использовать частные MOC. В то время как частные MOC приятны и полезны, структура каждого действия должна быть в блоке и что вы не можете получить доступ к результирующим NSManagedObject экземплярам, ​​за исключением того, что эти блоки ограничены. Создайте поток, ограниченный MOC, в очереди, а затем получите более чистый код, чем нужно постоянно погружаться в блоки (или, что еще хуже, создавать огромные блоки, не поддерживающие maintanable).

И наконец. Вы проходите nil до -save:. Никогда не делайте этого. Когда вы это делаете, вы скрываете потенциальную проблему. Даже если «это всего лишь пример», это ужасная привычка, и вы должны немедленно ее разбить. Даже в примере кода перейдите в NSError и проверьте ошибку. Даже если вы просто передадите результаты NSLog, вы, по крайней мере, избежите сюрприза.

+1

IMO, передающий 'nil' для аргумента' NSError ** ', в любом случае ошибочен. Это аргумент указателя, поэтому 'NULL' будет правильным, для немногих случаев, когда вы действительно искренне * не заботитесь об ошибке. – alastair

+0

Насколько я могу судить, дочерние MOC все еще сильно разбиты на Mavericks (отношения между вновь вставленными объектами ломаются на save. GetPermanentIDsForObjects перед сохранением решает проблему, но это раздражает, если не сказать больше). Вы действительно рекомендуете их использовать? –

+0

@fabricetruillotdechambrier: короткий ответ; да. Их легче перебирать. Края менее резкие, чем другие. Являются ли они самыми результативными? Нет, но они являются более четким способом создания многопоточного компакт-диска. Если вам комфортно/опытным с другими решениями, то идите за ними, но я не рекомендую их разработчикам, только начинающим работу с Core Data. –

1

Сохранение, вероятно, произойдет в потоке, на который он был вызван. Каковы последствия? Мы не знаем реализации, поэтому мы можем только догадываться. Иногда неправильное использование управляемых контекстов и управляемых объектов может привести к действительно странному поведению, и вы даже не подумаете, что это из-за ошибки потоковой передачи.

Вся работа с контекстами и управляемыми объектами должна выполняться в потоке или очереди, где они были созданы. В принципе это то же самое для традиционных контекстов и для контекстов с типом параллелизма с частными очередями. Последние просто создают очередь для вас и всегда сохраняют ее с собой.

Смежные вопросы