Возможно ли разработать подклассы NSCell в Interface Builder?
Я пытаюсь подклассифицировать NSCell для использования в NSTableView. Ячейка, которую я хочу создать, довольно сложна, поэтому было бы очень полезно, если бы я мог ее создать в Interface Builder, а затем загрузить NSCell из низа.
Возможно ли это? Как это сделать?
Ответы
Ответ 1
Вопрос был о подклассе NSCell; другие ответы, похоже, делают что-то еще, вероятно, используя UITableViewCell, являющийся представлением.
NSCell - это не представление. Хотя закладка пользовательской ячейки в IB была бы полезной, чтобы быть в состоянии сделать, я думаю, что ответ в основном "нет, это невозможно". Когда вы подклассе NSCell, вы в значительной степени просто делаете свой собственный рисунок. Существует не поддержка subcells, или параметризованная автоматическая компоновка (ala NSView springs и struts), что я подозреваю, что вы ищете.
Единственное предостережение заключается в том, что вы можете создать подкласс NSCell, который сделал макет субэлементов и предоставил параметры для настройки этих подэлементов и всех настраиваемых параметров. Затем вам нужно будет написать плагин IB, чтобы сделать эту ячейку и сопровождающий инспектор доступным во время разработки в IB.
Однако это, вероятно, сложнее, чем писать небольшое пользовательское приложение, которое делает более или менее одно и то же. Поместите NSCell в элемент управления посередине окна и сделайте себе интерфейс для настройки параметров, которые вам интересны. Привязки могут сделать это довольно простым для позиционирования материала (т.е. Привязать значение x к слайдеру), хотя вы будете не получить прямое управление элементами, конечно. Когда вы закончите, вы можете архивировать свою ячейку и загружать архив во время выполнения в реальном приложении, или вы можете просто выйти из свойств и установить их в коде в своем приложении.
Ответ 2
Некоторые ответы в этой теме исчезли из-за того, что они говорят о Cocoa Touch, когда исходный вопрос был о Cocoa - в этом отношении два API-интерфейса сильно отличаются друг от друга, а Cocoa Touch упрощает потому что UITableViewCell является подклассом вида. NSCell нет, и что проблема
Для информации мне пришлось сделать что-то очень похожее в NSOutlineView в последнее время - это в основном то же самое, но немного сложнее, если что-то, потому что вам приходится иметь дело с раскрытием/срывом уровней. Если вас интересует код, я разместил его здесь: http://www.stevestreeting.com/2010/08/08/cocoa-tip-using-custom-table-outline-cells-designed-in-ib/
НТН
Ответ 3
Как говорит Кен, NSCells
и NSViews
различаются, и вы можете размещать иерархии NSView
только в NIB, а не NSCells
(которые не имеют явной иерархии).
С другой стороны, ничто не мешает вам иметь иерархию NSViews
и использовать это, чтобы нарисовать ваш NSCell
- вы могли бы добавить их в качестве подсмотра родительского представления вашей ячейки, сообщить им для отображения и удалите их из окна, и никто не станет мудрее.
В этом случае использование NIB будет работать, хотя это похоже на тонну хлопот. Обычно я только что заменил объект, который принимает NSCells
с пользовательским, который принимает мой NSViews
, но это означает, что вы можете написать свой собственный код обработки мыши, который очень обидчив.
С другой стороны, мой подход позволяет привязывать значения представлений в NIB, поэтому вам не нужно выполнять какую-либо дополнительную работу, а это круто.
Ответ 4
В IB запустите пустой XIB. Теперь перейдите в палитру и перетащите ее в UITableViewCell, дважды щелкните, чтобы открыть и отредактировать.
включает только пользовательский UITableViewCell (нет других UIViews или других элементов верхнего уровня) - убедитесь, что он является реальным UITableViewCell в IB, или вы не можете установить идентификатор повторного использования (в отличие от литья UIView в IB как ваш пользовательский класс UITableViewCell), Затем вы можете добавить в ячейку ярлыки или что угодно, а также установить идентификатор повторного использования или установить любой индикатор раскрытия, который вам может понравиться.
Чтобы использовать, вы предоставляете такой код в таблицеView: 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 с помощью кода Cocoa Touch, который я использовал выше, поскольку loadNibNamed является стандартным вызовом Cocoa.
Ответ 5
Joar Wingfors написал статью для Stepwise несколько лет назад по соответствующей теме Subviews в рядах TableView.
Основной метод - создать NSCell, который может разместить NSView. Если бы вы это сделали, тогда вы могли бы создать подкласс NSView в Interface Builder, который вы могли бы внедрить в любом месте, где вам нужна эта конкретная ячейка.
Другая возможность, если вы можете настроить Leopard, - это посмотреть, нужно ли вам использовать NSTableView или использовать NSCollectionView. Представления коллекции напрямую рассматриваются в терминах "представления элементов", а не в ячейках, поэтому они гораздо проще разрабатывать в Interface Builder.
Ответ 6
Я нашел несколько интересных примеров, которые я не совсем понимаю.
Последние 2 примера работают с NSTableViewDataSource
и NSTableViewDelegate
. Я хотел бы использовать Bindings
a ArrayController
в InterfaceBuilder
для подключения других элементов пользовательского интерфейса, таких как текстовые поля.
Ответ 7
Я делаю это так:
/* 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, который должен заставить этот код запускать только несколько раз за таблицу.
Ответ 8
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;
Надеюсь, это поможет =)
Ответ 9
Я хочу предложить более современный подход здесь.
Начиная с iOS 5, UITableView имеет метод
(void)registerNib:(UINib *)nib forCellReuseIdentifier:(NSString *)identifier
После регистрации вашего NIB, содержащего вашу ячейку, просто используйте
- (id)dequeueReusableCellWithIdentifier:(NSString *)identifier
чтобы получить новую ячейку. Если ячейка доступна для повторного использования, она будет возвращена, в противном случае новая ячейка будет автоматически создана, и в этом случае это означает, что она загружена из файла NIB.
Ответ 10
Добавьте 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;