Редактируемое табличное представление привязано к NSArrayController, привязанному к NSUserDefaultsController

У меня есть простая модель Foo, которая представляет предпочтения пользователя и инкапсулирует NSString и NSNumber. Я хочу сохранить массив Foo в пользовательских значениях по умолчанию, чтобы они сохранялись между запусками приложения; и я хотел бы отображать их в виде таблицы, чтобы пользователь мог добавлять, удалять и редактировать их. Решение этой проблемы с привязками казалось довольно простым, но для меня оказалось невозможным приступить к работе.

Когда мое приложение запускается, я регистрирую в NSUserDefaults архив с ключами массива начальных Foo. В моем XIB у меня есть контроллер массива с его массивом содержимого, привязанным к values ключу контроллера общего пользователя по умолчанию; с ключевым путем foos; Установлен флажок «Обрабатывать контент как составное значение»; и NSKeyedUnarchiveFromData как преобразователь значений. Представление таблицы затем, в свою очередь, привязывается к контроллеру массива, а столбцы таблицы - к свойствам Foo.

Это отлично работает, когда Foo добавляются и удаляются из массива - ключ foos в пользовательских значениях по умолчанию обновляется, чтобы отразить новое содержимое массива. Проблема в том, что изменения в свойствах отдельного Foo не приводят к тому, что массив аналогичным образом возвращается к пользовательским значениям по умолчанию. Я считаю, что причина этого обсуждается в 'Отношения ко многим 'раздела' Регистрация зависимых ключей 'в Руководстве по программированию наблюдения за значениями ключа: изменения в самом массиве контроллера массива наблюдаются, но изменения свойствам содержащихся элементов нет.

Несмотря на то, что я признаю это проблемой, я всю жизнь не могу понять, что на самом деле делать, чтобы это сработало. Когда я наблюдаю изменение Foo, о каком объекте мне нужно сообщить и с каким сообщением, чтобы весь массив был записан обратно к пользовательским значениям по умолчанию - NSUserDefaults, NSUserDefaultsController, NSArrayController? Хотелось бы, чтобы в документации Apple было больше, чем поверхностное упоминание об этой проблеме и был приведен реальный пример кода для ее решения - я все перепробовал и не могу найти волшебное заклинание.

Это похоже на Как получать уведомления об изменениях к моделям через NSArrayController, но я не могу сделать концептуальный скачок между тем, что он делает с пользовательским представлением, и использованием bind:toObject:withKeyPath:options:.

Спасибо! :)


person Cody Robbins    schedule 10.05.2013    source источник
comment
Это действительно похоже на работу CoreData, а не NSUserDefaults.   -  person Brad Allred    schedule 23.10.2013
comment
Вы можете уточнить? Одна только мысль о том, какой объем документации мне нужно было бы переварить, чтобы даже начать реализовывать это с помощью CoreData, вызывает у меня головную боль. С точки зрения модели данных то, что я пытаюсь сделать, кажется чрезвычайно простым - учитывая сложность CoreData, здесь это кажется излишним.   -  person Cody Robbins    schedule 30.10.2013
comment
ну, пользовательские значения по умолчанию предназначены для настройки, и вы пытаетесь использовать его для хранения своей модели данных, формируя ее звук. CoreData действительно не так уж и сложен, если у вас действительно простая модель данных. В xcode есть шаблоны проектов, которые в основном делают всю настройку за вас. он также должен решить проблему, которую вы описываете.   -  person Brad Allred    schedule 30.10.2013
comment
Я должен согласиться с Брэдом. CoreData - это действительно правильный путь, и это действительно не так сложно, как может показаться (если бы все системы баз данных были такими простыми).   -  person Lloyd Sargent    schedule 17.01.2016


Ответы (1)


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

Я не мог сказать наверняка, но похоже, что вы хотите получать уведомление, когда какое-либо свойство любого Foo изменяется, чтобы вы могли сигнализировать об изменении вашего массива foos и, таким образом, NSUserDefaults обновлять сохраненный массив. Это правильно?

Предполагая, что я понимаю сценарий, и учитывая, что, как вы сказали, изменение самого массива (т.е. добавление / удаление Foo внутри 'foos' успешно сигнализирует об изменении, кажется очевидным, что вам нужно указать, что foos был обновляется каждый раз, когда обновляется отдельное свойство.

Для этого вам просто нужно запустить уведомление KVO при изменении любого свойства. По сути, вы должны переопределить свои сеттеры внутри Foo - для любых свойств, которые вы заботитесь о наблюдении. И отправьте уведомление туда.

Но как ты это делаешь? Обычный шаблон для отправки уведомления KVO выглядит примерно так (для свойства с именем openBalance:

[self willChangeValueForKey:@"openingBalance"];
_openingBalance = theBalance;
[self didChangeValueForKey:@"openingBalance"];

Но в вашем случае вы хотите отправить уведомление об изменении свойства foos. И это не собственность на Foo. Нет ничего, что говорило бы, что уведомление должно быть только для определенного свойства (или, по крайней мере, ничего, о чем я знаю). Но вы, вероятно, не хотите, чтобы Foo знал, что он находится внутри свойства 'foos' где-то еще.

Итак, как насчет использования простого NSNotification? Создайте общий метод для запуска обновленного уведомления «Foo» внутри Foo - подклассифицируйте свои сеттеры, а затем запускайте это уведомление всякий раз, когда вы изменяете свойство Foo.

В свою очередь, внутри вашего объекта, которому принадлежит 'foos', подпишитесь на это уведомление и либо напрямую обновите NSUserDefaults, либо оттуда активируйте свои KVO-уведомления для 'foos'.

person Bladebunny    schedule 26.10.2013