Разрешение конфликта NSManagedObject с несколькими потоками, отношениями и указателями - PullRequest
0 голосов
/ 24 февраля 2011

У меня конфликт при сохранении группы NSManagedObjects через внешний поток.Для начала я могу сказать вам следующее:

  1. Я использую отдельный MOC для каждого потока.
  2. MOC используют один и тот же постоянный координатор хранилища.
  3. Вероятно, что внешний поток изменяет одну или несколько записей, которые я сохраняю.

ОК, так что с этим, вот что я делаю.

В моем внешнем потоке я выполняю некоторые вычисления и обновляю одно значение в группе управляемых объектов.Я делаю это, просматривая объект в постоянном хранилище по первичному ключу, изменяя одно десятичное свойство, а затем вызывая save для сгустка сразу.

Между тем, я считаю, что основной потоквыполняя свое собственное обновление.

Когда мой внешний поток делает большую экономию в контексте управляемого объекта, я получаю исключение, указывающее большое количество конфликтов.Кажется, что все конфликты связаны с отдельными отношениями в каждой записи.Хотя управляемый объект в постоянном хранилище и моем внешнем потоке совместно использует один и тот же ObjectID для этого отношения, они не разделяют один и тот же указатель.Исходя из того, что я вижу, это единственное, что отличается между объектами в моем выводе отладки NSMergeConflict.

Для меня имеет смысл, почему два объекта имеют отношения с разными указателями - они находятся в разных потоках.Однако, как я понимаю из документации Apple, единственное, что кэшируется при первом извлечении объекта из постоянного хранилища, это глобальные идентификаторы.Таким образом, можно подумать, что когда я запускаю save во внешнем потоке MOC, он сравнивает ObjectID, видит, что они одинаковы, и пропускает все это.

Итак, кто-нибудь может сказать мне, почему яполучить конфликт?

Ответы [ 3 ]

2 голосов
/ 24 февраля 2011

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

Кроме того, в разделе Отслеживание изменений в других потоках с помощью уведомлений той же главы говорится, что если вы отслеживаете обновления с помощью NSManagedObjectContextDidSaveNotification , то отправляете -mergeChangesFromContextDidSaveNotification в контекст основного потока, чтобы он мог объединить изменения. Но если вы отслеживаете NSManagedObjectContextDidChangeNotification , тогда внешний поток должен отправить идентификаторы объектов измененных объектов в основной поток, который затем отправит -refreshObject: mergeChanges: в свой контекст для каждый измененный объект.

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

0 голосов
/ 26 февраля 2011

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

0 голосов
/ 25 февраля 2011

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

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

...