2012-01-12 2 views
1

Каков наилучший способ заполнения NSTableView пользовательскими ячейками?Пользовательские ячейки в NSTableView

Я всегда использую привязки какао, когда я заполняю стандартные данные, и всегда использую источники данных, когда заполнены таблицы с пользовательскими ячейками. Мне интересно, есть ли способ смешивания двух концепций для оптимального дизайна.

Использование Xcode 3 (и, следовательно, IBPlugins), к сожалению, не является вариантом.

+0

Пожалуйста, следуйте инструкциям ниже и сделайте все правильно. Если это действительно помогает –

ответ

3

Я лично не буду mix Связанные данные и источники данных. Я не встречал ничего, кроме боли, пытающейся это сделать. У меня есть несколько подходов, которые могут вам помочь.

Одна вещь, которую я смог сделать, это установить пользовательский класс ячеек в IB, который является подклассом одной из ячеек, о которых знает IB, а затем переопределить все, что вам нужно, чтобы заставить его делать то, что нужно. вы хотите. Но сначала некоторый фон и некоторые пропущенные попытки:

При привязке к NSTableViews на основе ячеек вы обычно устанавливаете привязки для самого столбца, а не для ячейки внутри столбца. Если вы используете пользовательский подкласс NSCell в столбце таблицы, вы заметите, что привязки, такие как value, больше не доступны в столбце, в отличие от того, когда ячейка является NSTextFieldCell. Я попытался сортировать трюк IB, установив привязку value с ней, настроенную как NSTextFieldCell, а затем отключив ячейку - привязка все еще появляется в инспекторе привязок, но она всегда вылетает во время выполнения с этой ошибкой: [<NSTableColumn 0x10252e910> valueForUndefinedKey:]: this class is not key value coding-compliant for the key value.

Это подводит меня к подклассу одной из ячеек, которую IB знает, как привязываться. Я создал подкласс NSTextFieldCell, развернутый до «Text Field Cell - текстовая ячейка» в столбце таблицы, а затем установил свой собственный подкласс в Identity Inspector. Я смог подтвердить, что привязки все еще работают, и IB по-прежнему рассматривает его как NSTextFieldCell. Оттуда я мог бы переопределить любые методы, которые мне нужны в моем классе ячеек, и получить пользовательское поведение. У меня нет оснований полагать, что вы не могли бы это сделать и с ячейками изображения. Естественно, это своего рода поддельный подход, но в зависимости от того, как «пользовательские» ваши пользовательские ячейки, он может бить писать кучу пользовательского кода для подключения источника данных.

Что я узнал о дальнейших экспериментах, так это то, что это проблема «IB» и не проблема NSTableView/bindings. И есть еще один неплохой путь.

Предположим, вы хотите использовать пользовательскую ячейку и хотите привязать ее к произвольному объекту модели. У вас есть привязка к значению NSTableColumn, привязанная к NSArrayController, которая продает список объектов пользовательской модели, каждый из которых имеет свойство, называет его dataForCustomCell, который возвращает все, что требуется для пользовательской ячейки. Вы бы установили столбец TextFieldCell (например, значение по умолчанию в IB), затем привяжите привязку value контроллера NSTableColumn к контроллеру массива>arrangedObjects и введите путь ключа модели dataForCustomCell. На этом этапе, предполагая, что объект, возвращенный dataForCustomCell, реализует NSCopying (если это не приведет к сбою вашего приложения, но это не очень важно для этой второй), то, что вы увидите, если вы запустили приложение, это то, что NSTextFieldCell будет звонить - (NSString*)description на объект возвращается dataForCustomCell и помещает этот текст в ячейку.

Теперь самое интересное: В -awakeFromNib время в вашей владеющим объекта (NSView, NSViewController, и т.д., и т.д.), заменить Datacell (и headerCell, если вам нравится), как это:

- (void)awakeFromNib 
{ 
    [super awakeFromNib]; 
    // Assuming you've got your NSTableView plugged into an IBOutlet property called table 
    NSTableColumn* col = [[self.table tableColumns] objectAtIndex:0]; 
    col.dataCell = [[[MYCustomCell alloc] init] autorelease]; 
} 

С привязки находятся на NSTableColumn, а не на самой ячейке, вы можете поменять ячейку, не беспокоясь о повторном подключении любых привязок. В вашем пользовательском классе ячейки переопределите -(void)setObjectValue:, и вы получите вызов из механизма привязок во время выполнения, нажав на объект, который пришел из свойства dataForCustomCell, на объект модели, соответствующий текущей чертежной таблице. (Вы также получите вызов, проходящий в ноль для каждой ячейки, но, похоже, безопасно игнорировать это или просто передать его супер).

Один из недостатков этого подхода заключается в том, что вы получаете только одно значение «Значение», обязательный для NSTextFieldCell. Обходной путь для этого состоит в том, чтобы связать привязку Value с большей/более высокой «гранулой» в вашей модели, а затем развернуть и развернуть несколько значений в вашей реализации -setObjectValue:, если это необходимо.

Это не идеальный вариант, но это исправление «пара строк кода» вместо исправления «gazillions of lines of code».

Альтернативно, предполагая, что вы нацеливаете довольно недавние версии MacOS, вы также можете работать с NSTableViews на основе представлений. Они довольно приятные, и привязывают привязки гораздо более разумным способом, чем таблицы на базе NSCell. Это совсем другой способ делать что-то, поэтому трудно сказать, как ваша задача будет сопоставляться с ним. Есть great video on the Apple developer site, который подводит вас к скорости NSTableView на основе NSView.

+0

Отличный ответ, спасибо за обмен опытом. –

+0

Превосходное объяснение !!! –

Смежные вопросы