Можно ли спроектировать подклассы NSCell в Интерфейсном Разработчике? - PullRequest
22 голосов
/ 14 октября 2008

Я пытаюсь создать подкласс NSCell для использования в NSTableView. Ячейка, которую я хочу создать, довольно сложна, поэтому было бы очень полезно, если бы я мог спроектировать ее в Интерфейсном Разработчике и затем загрузить NSCell из пера.

Возможно ли это? Как мне это сделать?

Ответы [ 10 ]

11 голосов
/ 15 октября 2008

Вопрос был о подклассе NSCell; другие ответы, кажется, делают что-то другое, вероятно, используя преимущество UITableViewCell, являющегося представлением.

NSCell не является представлением. Хотя было бы полезно сделать пользовательскую ячейку в IB, я думаю, что ответ в основном «нет, это невозможно». Когда вы создаете подкласс NSCell, вы просто делаете свой собственный рисунок. Нет поддержки суб-ячеек или параметризованного автоматического размещения (а именно пружины и стойки NSView), что, как я подозреваю, вы ищете.

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

Однако это, вероятно, сложнее, чем написать небольшое специальное приложение, которое выполняет более или менее одно и то же. Поместите NSCell в элемент управления в середине окна и создайте себе пользовательский интерфейс для настройки интересующих вас параметров. Привязки могут сделать это довольно простым для позиционирования (например, привязать значение x к ползунку), хотя вы это сделаете Конечно, не получить непосредственное управление элементами. Когда вы закончите, вы можете заархивировать свою ячейку и загрузить архив во время выполнения в вашем реальном приложении, или вы можете просто выйти из свойств и установить их в коде в вашем приложении.

11 голосов
/ 08 августа 2010

Некоторые ответы в этой теме вышли за рамки темы, потому что они говорят о Cocoa Touch, когда первоначальный вопрос был о Какао - два API-интерфейса сильно отличаются в этом отношении, и Cocoa Touch упрощает, потому что UITableViewCell является подклассом представления , NSCell нет, и это проблема

Для информации, мне недавно пришлось сделать что-то очень похожее в NSOutlineView - что в принципе то же самое, но немного сложнее, потому что вам приходится сталкиваться с раскрытием / обвалом уровней. Если вы заинтересованы в коде, я написал об этом здесь: http://www.stevestreeting.com/2010/08/08/cocoa-tip-using-custom-table-outline-cells-designed-in-ib/

НТН

7 голосов
/ 26 октября 2008

Как говорит Кен, NSCells и NSViews различны, и вы можете только выложить NSView иерархии в NIB, а не NSCells (у которых нет явной иерархии).

С другой стороны, ничто не мешает вам иметь иерархию NSViews и использовать ее для рисования NSCell - вы можете добавить их в качестве подпредставления родительского представления вашей ячейки, попросить их отобразить и уберите их из окна, и никто не станет мудрее.

В этом случае использование NIB работало бы, хотя это кажется кучей хлопот. Обычно я только что заменил объект, который берет NSCells, на пользовательский, который берет мой NSViews, но это означает написание вашего собственного кода для работы с мышью, который очень обидчив.

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

5 голосов
/ 15 октября 2008

В IB запустите пустой XIB. Теперь перейдите к палитре и перетащите в UITableViewCell, дважды щелкните, чтобы вызвать и редактировать.

включает только пользовательский UITableViewCell (без других UIViews или других элементов управления верхнего уровня) - убедитесь, что это настоящий UITableViewCell в IB, или вы не можете установить идентификатор повторного использования (в отличие от приведения UIView в IB в качестве пользовательского класса UITableViewCell) , Затем вы можете добавить метки или все, что вам нравится в ячейке, а также установить идентификатор повторного использования или установить любой индикатор раскрытия, который вам может понравиться.

Для использования вы предоставляете такой код в tableView: cellForRow: atIndexPath: method:

YourCustomCellClass *cell = (YourCustomCellClass *)[tableView dequeueReusableCellWithIdentifier:<IDYouSetInXIBFile>];
if ( cell == nil )
{
        NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:<YourXIBName> owner:self options:nil];
    id firstObject = [topLevelObjects objectAtIndex:0];
    if ( [ firstObject isKindOfClass:[UITableViewCell class]] )
        cell = firstObject; 
    else cell = [topLevelObjects objectAtIndex:1];
}

Если у вас есть какие-либо метки или другие элементы управления, на которые вы хотите сослаться в своем коде, подключите их в IB к вашему классу ячеек - НЕ к владельцу файла, который вам никогда не нужно устанавливать с помощью приведенного выше кода (вы можете оставить это как NSObject).

Редактировать: Я отмечаю, что вы действительно ищете ответ NSCell, но подход с использованием IB к коду должен совпадать с Cocoa Touch, который я использовал выше, так как loadNibNamed - это стандартный вызов Cocoa.

2 голосов
/ 17 октября 2008

Джоар Вингфорс написал статью для Stepwise несколько лет назад по связанной теме Подвиды в строках TableView .

Основной метод заключается в создании NSCell, который может содержать NSView. Если бы вы сделали это, вы могли бы тогда создать подкласс NSView в Интерфейсном Разработчике, который вы могли бы внедрить в любое место, где вам нужна эта конкретная ячейка.

Другая возможность, если вы можете использовать Leopard, заключается в том, чтобы узнать, нужно ли вам использовать NSTableView или вы можете использовать NSCollectionView. Представления коллекций имеют дело непосредственно с «представлениями элементов», а не с ячейками, поэтому их гораздо проще проектировать в Интерфейсном Разработчике.

1 голос
/ 27 апреля 2011

Я нашел несколько интересных примеров, которые мне не совсем понятны.

Последние 2 примера работают с NSTableViewDataSource и NSTableViewDelegate. Я хотел бы использовать Bindings и ArrayController в InterfaceBuilder для подключения других элементов пользовательского интерфейса, таких как текстовые поля.

0 голосов
/ 07 мая 2014

Я хочу предложить более современный подход.

Начиная с iOS 5, у UITableView есть метод

(void)registerNib:(UINib *)nib forCellReuseIdentifier:(NSString *)identifier

Как только вы зарегистрируете свой NIB, содержащий вашу ячейку, просто используйте

- (id)dequeueReusableCellWithIdentifier:(NSString *)identifier

чтобы получить новую клетку. Если ячейка доступна для повторного использования, она будет возвращена, в противном случае автоматически создается новая ячейка, и в этом случае это означает загрузку из файла NIB.

0 голосов
/ 05 июня 2013

1) Создать NSViewController TableViewCell.h

2) Создайте в TableViewCell.h некоторые процедуры, такие как

-(void)setText:(NSString *)text image:(NSImage *)image

3) В основном классе #import "TableViewCell.h"

4) В основном классе в -(NSView *)tableView:viewForTableColumn:row: write:

NSImage *img = //some image
TableViewCell *cell = [[TableViewCell alloc] initWithWindowNibName:@"TableViewCell"];
cell.view.init;
[cell setText:@"some text" image:img];
return cell;

Надеюсь, это поможет =)

0 голосов
/ 27 декабря 2008

Добавьте ваш UITableViewCell к вашему tableviewcontroller и объявите свойство IBOutlet:

@interface KuguTableViewController : UITableViewController {
    IBOutlet UITableViewCell *customTypeCell;
}

@property (readonly)  UITableViewCell *customTypeCell;

... тогда в cellForRowAtIndexPath вы можете просто использовать свою ячейку и настроить ее для повторного использования:

static NSString *CellIdentifier = @"CustomCell"
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
        cell = customTypeCell;
        cell.reuseIdentifier = CellIdentifier;
0 голосов
/ 15 октября 2008

Я делаю это так:

/* example of a silly way to load a UITableViewCell from a standalone nib */

+ (CEntryTableViewCell *)cell
{
// TODO -- this is really silly.
NSArray *theObjects = [[NSBundle mainBundle] loadNibNamed:@"EntryTableViewCell" owner:self options:NULL];
for (id theObject in theObjects)
    if ([theObject isKindOfClass:self])
        return(theObject);
NSAssert(NO, @"Could not find object of class CEntryTableViewCell in nib");
return(NULL);
}

Однако это не очень эффективно, и если вы загружаете много данных, это может повредить вам. Конечно, вы должны использовать reuseIdentifier, который должен заставить этот код запускаться лишь несколько раз для каждой таблицы.

...