Странное родительское/дочернее явление 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/

Рассказ: они не так независимы, как вы думаете.

Используйте несколько контекстов, которые используют один постоянный координатор хранилища, если вам нужно больше одного контекста.