Обновить связывание какао - NSArrayController - ComboBox

В своем заявлении я сделал очень простую привязку. У меня есть NSMutableArray, связанный с NSArrayController. Сам контроллер привязан к ComboBox, и он показывает все содержимое NSMutableArray. Работает отлично.

Проблема в том, что содержимое массива изменится. Если пользователь вносит некоторые коррективы в приложение, я удаляю все элементы в NSMuteableArray и заполняю его новыми и разными элементами.

Но привязка NSMutableArray <-> NSArrayController <-> NSComboBox не обновляется.

Независимо от того, удаляю ли я все объекты из массива, ComboBox все равно показывает те же элементы.

Что здесь не так? Мой подход неверен или мне нужно только указать привязке, чтобы она обновлялась сама? Я не узнал, как это сделать.

3 ответа

Решение

Скорее всего, вы "редактируете массив за спиной контроллера", который подрывает механизм KVO.

Вы сказали:

У меня есть NSMutableArray, связанный с NSArrayController.

Как? Где живет массив? В документе, доступном через KVC/KVO-совместимый -myArray / -setMyArray: набор методов доступа?

Могу поспорить, что вы прямо говорите ивару myArray -removeAllObjects, верно? Как эти аксессоры KVC/KVO "узнают", что массив изменился?

Ответ - нет. Если вы действительно замените весь массив, вы захотите сообщить своему документу (или тому, кто владеет массивом) -setMyArray: всему новому массиву. Это вызовет правильные вызовы KVO.

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

(Документация - см. Раздел "Шаблоны доступа к коллекции для свойств To-Many") http://tinyurl.com/yb2zkr5

Попробуйте это (используя ARC/OS X 10.7):

в заголовочном файле определите arrayInstance и arrayController

 @property (weak) IBOutlet NSArrayController *arrayController;
 @property (strong) NSArray *arrayInstance; // for the array instance

затем в реализации

 @synthesize arrayController = _arrayController;
 @synthesize arrayInstance = _arrayInstance;

 _arrayInstance = .......  // What ever the new array will be
 [_arrayController setContent:_arrayInstance];

Это заставит arrayController обновлять содержимое и корректно отображаться.

Другое решение, кроме двух строк кода:

 [self willChangeValueForKey:@"arrayInstance"];
 _arrayInstance = .......  // What ever the new array will be
 [self didChangeValueForKey:@"arrayInstance"];

Думаю, первое выглядит более очевидным, второе более похожим на КВО.

Соблюдение KVC/KVO, похоже, является проблемой. Вы должны создать новый массив и обновить ссылку новым объектом, используя сгенерированные методы доступа. В противном случае вы можете запустить сообщения KVO об обновлении массива, чтобы сообщить привязкам, что содержимое массива изменилось.

Кристиан

Другие вопросы по тегам