Странное родительское/дочернее явление NSManagedObjectContext
Я создал два таких контекста:
// create writer MOC
_privateWriterContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[_privateWriterContext setPersistentStoreCoordinator:_persistentStoreCoordinator];
// create main thread MOC
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
_managedObjectContext.parentContext = _privateWriterContext;
У меня есть NSFetchResultedController
, начинающийся с _managedObjectContext
.
Я знаю, что это странно, но я добавляю запись родительскому элементу _privateWriterContext
, я saving
it.
Удивительно, что дочерний контекст и поэтому FRC
получает уведомление об этом событии. Зачем? У меня не есть reset
-ed ребенок, или что-то еще. Я думал, что они независимые объекты, пока детский контекст не будет сохранен.
В статье @pteofil я нашел эту строку:
Когда изменение производится в контексте, но не сохраняется, оно видимо для всех его потомков, но не для его предков.
.. он помещается в постоянное хранилище (через постоянный координатор хранилища) и становится видимым для всех контекстов, связанных с хранилищем.
Ответы
Ответ 1
Это не должно произойти. Добавление NSManagedObject ('record') в parentContext не приведет к тому, что ребенок будет знать об этом объекте автоматически. Только когда вы делаете childContext для выполнения выборки, он будет извлекаться из parentContext.
Чтобы выяснить, что происходит в вашем случае, вот несколько советов:
- выяснить, когда выборка выполняется в childContext (это выполняется с помощью fetchedRestultsController при его настройке. Проверьте, произошла ли эта выборка до или после добавления объекта managedObject в parentContext).
- установить точки останова во всех четырех обратных вызовах делегата fetchedResultsController, чтобы узнать, для какого объекта он вызывает методы (и посмотреть, является ли это объектом, который вы только что добавили в parentContext).
- убедитесь, что вы знаете, в каком контексте вы также отправляете сообщения.
У меня есть аналогичный подход, но другой: childContext - это контекст, используемый для анализа в новых данных (в частной очереди), и когда этот синтаксический анализ выполняется, chid вызывает save:. Это сохранит изменения до родителя, что в моем случае mainQueueContext. Этот вызов для сохранения: приведет к тому, что mainQueueContext получит все вновь обработанные объекты, и любой fetchedResultsController с использованием этого mainQueueContext затем вызовет его методы делегирования для новых/измененных/обновленных/удаленных объектов.
Вы также можете попробовать инвертировать отношения между дочерним и родительским отношением и посмотреть, работает ли он так, как описано в документах, чтобы узнать, что происходит.
Ответ 2
Я настоятельно рекомендую избегать установки родительского и дочернего контекстов. В нашей книге подробно описывается, почему они часто приводят к странному поведению: https://www.objc.io/books/core-data/
Рассказ: они не так независимы, как вы думаете.
Используйте несколько контекстов, которые используют один постоянный координатор хранилища, если вам нужно больше одного контекста.