У меня проблема с NSManagedObject, не отражающим изменения, внесенные в постоянное хранилище после того, как фоновый поток сохранил свой контекст.
Настройка
В простом тестовом приложении у меня есть одно окно, в котором перечислены все объекты в моем постоянном хранилище основных данных, поле поиска для фильтрации результатов и текстовое поле для отображения имени выбранного элемента и возможности изменения имени.
Привязки следующие:
ArrayController --> AppDelegate --> ManagedObjectContext TableView Col 1 --> ArrayController --> values --> arrangedObjects.widgetName TableView Col 2 --> ArrayController --> values --> arrangedObjects.uid SearchField --> ArrayController --> predicate --> filterPredicate TextField --> ArrayController --> value --> selection.widgetName
У меня также есть кнопка, которая запускает фоновую (NSOperation) выборку данных с веб-сервера.
Процесс
Когда пользователь нажимает кнопку обновления, запускается операция NSOperation, которая асинхронно захватывает виджеты, анализирует ответ, проверяет наличие локальных виджетов для удаления, которых нет в ответе, новых виджетов для добавления, которые не хранятся локально и существующих локальных виджеты, которые должны быть обновлены данными, полученными с сервера.
После завершения обработки основной контекст уведомляется с помощью:
[mainContext performSelectorOnMainThread:
@selector(mergeChangesFromContextDidSaveNotification:)
withObject:notification
waitUntilDone:YES];
У меня есть наблюдатель в главном контроллере для тестирования, который показывает, что изменения прошли нормально, и главный контроллер получил уведомление.
Проблема
Если я вношу изменение в выбранный объект с помощью текстового поля, при сохранении данных в фоновом потоке объект в пользовательском интерфейсе не обновляется, чтобы отразить эти изменения (т.е. он не перезаписывает пользовательский интерфейс изменениями из сервер).
Например, с учетом следующих трех виджетов и идентификаторов:
Test Name 1 | ID 123 Test Name 2 | ID 234 Test Name 3 | ID 345
Если я изменю имя в пользовательском интерфейсе Test Name 2
на Renamed 2
, у меня будет следующее:
Test Name 1 | ID 123 Renamed 2 | ID 234 Test Name 3 | ID 345
Когда я обновляюсь в фоновом режиме, я хочу, чтобы список отражал состояние сервера, то есть возвращался к:
Test Name 1 | ID 123 Test Name 2 | ID 234 Test Name 3 | ID 345
Вместо этого остается:
Test Name 1 | ID 123 Renamed 2 | ID 234 Test Name 3 | ID 345
Я знаю, что постоянное хранилище было обновлено, потому что если я убью приложение из XCode и перезапущу его, отобразится желаемая информация. Если я выхожу из приложения в обычном режиме, измененное значение записывается в хранилище при закрытии приложения, и при повторном открытии отображается переименованное значение.
Что я пробовал
Я знаю, что сообщение отправляется из фона в основной контекст, и я знаю, что данные сохраняются в магазине. Следовательно, проблема, я считаю, заключается в том, что основной контекст не объединяется, как я ожидал, или мне нужно каким-то образом заставить контроллер массива выполнять выборку из постоянного хранилища и отбрасывать его контекст.
- Я попробовал
processPendingChanges:
при получении уведомления о сохранении в магазине, но подозреваю, что просто пишуRenamed 2
в магазин. - Я пробовал сделать
rearrangeObjects
на контроллере массива, но поскольку контроллер массива имеет дело с основным контекстом, я подозреваю, что это ничего не делает - Я попытался выполнить
fetch:nil
на контроллере массива, чтобы выполнить выборку из постоянного хранилища, но я снова подозреваю, что основной контекст перезаписывает значениеRenamed 2
, потому что оно еще не сохранено. - Я пробовал
fetchWithRequest:nil merge:NO error:&error
на контроллере массива в соответствии с документами Apple, но, похоже, это не меняет отображаемое значение
Я думаю, что должно произойти, чтобы контроллер массива сохранил свои данные в постоянном хранилище, прежде чем я запишу данные фонового хранилища, так что выборка на контроллере массива приведет к тому, что данные будут точными, как согласно моим ожиданиям. И если это действительно так, как я могу сказать контроллеру массива сделать это, или контроллер массива просто узнал бы об изменениях через привязки, если бы основной managedObjectContext был каким-то образом сохранен?
Я могу взломать решение, выполнив выборку из постоянного хранилища, поместив эти данные в массив и выполнив setContent:
на контроллере массива, а затем повторив это, когда постоянное хранилище сохранено, но это кажется просто неправильным, не говоря уже о проблеме о необходимости отслеживать выбранное состояние контроллера массива (и, возможно, любые выборки подмассивов, которые могут произойти в результате этого первичного выбора).
Я не на базе? Я явно что-то здесь упускаю.
Будем очень признательны за любые мудрые слова или совет.