NSTableView при поддержке NSArrayController: почему setContent: работает, а IB - нет? - PullRequest
4 голосов
/ 30 октября 2011

Я пытаюсь реализовать в значительной степени простейший случай привязки NSTableView к NSArrayController, так что NSTableView поддерживается NSArray.

Вот настройка:

  1. У меня есть NSArrayController, чей «Массив содержимого» связан с NSArray в моем делегате приложения.
  2. В 'Object Controller' NSArrayController имя класса установлено на Model, тип объектов, содержащихся в NSArray.
  3. «Значение» одного столбца NSTableView привязано к ключу «name» ofagedObjects Array Controller, который является единственным полем класса Model.
  4. В applicationDidFinishLaunching: моего делегата приложения я инициализирую NSArray и вставляю некоторые объекты Model.

Тем не менее, строки, соответствующие модели, не появляются в таблице, если я также не сделаю: [self.arrayController setContent: self.array].

Есть ли способ заставить это работать, используя привязки, связанные в Интерфейсном Разработчике? Я ожидал, что тот факт, что NSArrayController 'Content Array' связан напрямую с NSArray, означает, что мне не придется устанавливать контент программно. Знание почему поможет мне лучше понять привязки.

1 Ответ

13 голосов
/ 30 октября 2011

Ваш контроллер массива наблюдает за свойством массива вашего делегата приложения. Это означает, что уведомления KVO отправляются только тогда, когда установлен объект массива, а не когда к нему добавляются объекты. Похоже, вы используете NSMutableArray и добавляете в него объекты, что объясняет, почему контроллер массива не уведомляется об изменениях, поскольку базовый объект не меняется.

Простое решение состоит в том, чтобы обернуть ваши звонки в блок воли / изменения, например:

[self willChangeValueForKey:@"array"];
[self.array addObject:[NSDictionary dictionaryWithObject:@"foo" forKey:@"name"]];
[self.array addObject:[NSDictionary dictionaryWithObject:@"bar" forKey:@"name"]];
[self didChangeValueForKey:@"array"];

Это вручную уведомляет наблюдателей об изменении свойства "array".

Длинный ответ: Вы делаете это неправильно. Весь смысл наличия контроллера массива состоит в том, чтобы перенести работу по управлению массивом на сам класс контроллера, чтобы он управлял базовым массивом, отправлял правильные уведомления, поддерживал состояние и т. Д., Не прибегая к потере деталей реализации. Лучшим решением было бы отцепить привязку массива контента и просто добавить объекты в контроллер массива, например, так:

[arrayController addObject:[NSDictionary dictionaryWithObject:@"foo" forKey:@"name"]];
[arrayController addObject:[NSDictionary dictionaryWithObject:@"bar" forKey:@"name"]];

Это работает, потому что контроллер массива управляет своим собственным массивом внутри.

Лучшее решение - использовать Core Data. NSArrayController предназначен для использования с ним. Вы также бесплатно получаете целый набор вещей, таких как постоянство, поддержка отмены, отношения объектов и возможность добавлять объекты без написания кода, просто вызывая add: на контроллере массива непосредственно из элементов управления вашего пользовательского интерфейса.

...