Обновить связывание какао - 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 об обновлении массива, чтобы сообщить привязкам, что содержимое массива изменилось.
Кристиан