Подтвердить что ты не робот

Когда вызывать getPermanentIDsForObjects:?

В настоящее время у меня проблема с созданием нового объекта в фоновом дочернем потоке (родительский - это основной контекст потока пользовательского интерфейса) и сохранение заставляет мой NSFetchedResultsController показывать два новых объекта: один с временным objectID, и один с постоянным objectID. Кажется, это какая-то ошибка, если я не пропущу что-то.

Итак, я думал, что буду вручную получать постоянные идентификаторы для любых новых объектов, которые я создаю. Это исправляет проблему с повторяющейся строкой, но вводит новые случайные ошибки (например, "не может выполнить ошибку для объекта", ссылаясь на новый объект, который я создал). Если у кого-то есть какие-либо идеи относительно того, почему происходит какое-либо из ранее упомянутых событий, пожалуйста, поделитесь им.

Я предполагаю, что obtainPermanentIDs - это шаг в правильном направлении. Но когда я называю этот метод? Перед сохранением в контексте ребенка? После сохранения ребенка и перед родителем? После родителя? В настоящее время моя настройка такова:

masterMOC - private queue tied to the persistent store, so physical saves happen here
----mainMOC - main queue tied to the UI, child of masterMOC
-------backgroundMOC - private queue, child of mainMOC

Итак, если я создаю новый объект на backgroundMOC, и я намерен немедленно сохранить его на диск (это означает, что мне нужно будет вызвать save: во всех трех контекстах), где я должен звонить obtainPermanentIDs?

(или если у кого-то другое решение, отличное от вызова, получение постоянных идентификаторов? Какая проблема была введена в любом случае для решения? Почему бы мне назвать этот метод?)

Update: Я думаю, что я понял, что происходит (это только теория), хотя и не как ее решить. Core Data, по-видимому, генерирует постоянные идентификаторы для объектов, когда они физически сохраняются на диск. Так что в моем случае это произойдет не до тех пор, пока я не вызову save на masterMOC. В настоящее время я создаю новый объект на backgroundMOC:

  • сохранить на backgroundMOC (чтобы изменения были сдвинуты на один уровень до mainMOC, и мой вид таблицы может вставлять новые строки)
  • сохранить mainMOC (чтобы я мог подготовиться к сохранению на диске)
  • сохранить на masterMOC (который, наконец, сохраняется на диск)

Что происходит, так это то, что вызов save на backgroundMOC запускает обновление пользовательского интерфейса и заставляет получателя результатов вводить новый объект, который все еще имеет только временный идентификатор. Но затем вызов save на masterMOC заставляет все объекты получать назначенные постоянные идентификаторы, что вызывает другое обновление пользовательского интерфейса, вставляя еще одну строку для этого "нового" объекта! Комментируя последнее сохранение masterMOC, я больше не вижу повторяющихся записей. Я здесь что-то не так, или это какая-то ошибка?

Другое обновление: Я думаю, что я очень хорошо подтвердил ошибку. Я вызываю save на backgroundMOC, а затем настраиваю таймер для вызова save на mainMOC и masterMOC через 5 секунд. Immediatley при сохранении на backgroundMOC, новая строка вставляется в мою таблицу. Через 5 секунд (при сохранении основного и основного) вставляется новая новая строка. (сначала вставленная строка имеет временный идентификатор, а самая новая вставка имеет постоянный идентификатор).

4b9b3361

Ответ 1

У меня была одна и та же проблема, конечно, после особо сложного и унылого дня отладки всего, чтобы узнать, что проблема связана с временными идентификаторами.:)

Я имею ту же структуру, что и вы, и у меня также есть подклассы NSManagedObjectContext для кодирования поведения, которое я ожидаю от сохранения в фоновом режиме и в основных контекстах, а именно: сохранение в фоновом контексте должно сохранять основной контекст (и главный контекст должен синхронизировать любые объекты, которые были изменены с внешней службой, что не имеет значения, но стоит упомянуть в качестве объяснения, почему у меня есть два подкласса), а сохранение в главном контексте должно сохранить основной контекст.

В моем подклассе RFSImportContext (эквивалентном вашему backgroundMOC) я реализую - save: для вызова [super save:], а затем вызов [self.parentContext performBlock:] (self.parentContext здесь эквивалентен вашему mainM) C, где блок вызывает obtainPermanentIDsForObjects: с содержимым основного контекста - updatedObjects и - insertedObjects массивов, тогда я сохраняю основной контекст.

У меня больше нет утечки временных объектов в мой NSFetchedResultsController, как вы описываете. Для улучшения ситуации немного было бы использовать подкласс RFSMainContext (опять же, эквивалентный вашему mainMOC), чтобы реализовать - save: для получения идентификаторов постоянных объектов, сохранить себя, а затем сохранить главный контекст. Это кодирует поведение, которое мы всегда хотим, чтобы основной контекст имел постоянные идентификаторы для объектов в нем, когда он сохраняется.