У меня проблемы с 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 Docs, но, похоже, это не меняет отображаемое значение
Я думаю, что должно произойти, чтобы контроллер массива сохранил свои данные в постоянном хранилище, прежде чем я запишу данные фонового хранилища, так что выборка на контроллере массива приведет к тому, что данные будут точный согласно моим ожиданиям. И если это действительно так, то как бы я сказал контроллеру массива сделать это, или же контроллер массива просто узнает об изменениях через привязки, если будет сохранен главный управляемый объект-объект как-нибудь?
Я могу взломать решение, выполнив выборку из постоянного хранилища, поместив эти данные в массив и выполнив setContent:
на контроллере массива, а затем повторите это при сохранении постоянного хранилища, но это выглядит просто неправильно,не говоря уже о том, что необходимо отслеживать выбранное состояние контроллера массива (и, возможно, любые выборки подмассива, которые могут произойти в результате этого первичного выбора).
Я вне базы?Я, очевидно, что-то здесь упускаю.
Любые мудрые слова или советы будут очень признательны.