2009-07-31 3 views
4

Я успешно создал NSCollectionView и добавил метку к прототипу представления в IB, привязанному к свойству моего объекта. Теперь я хочу программно создать NSButton и NSTextField с NSTextField, привязанным к свойству моего объекта. Когда кнопка нажата, я хочу показать и скрыть NSTextField.Как связать программно в подклассе вида моего NSCollectionView?

Проблема, с которой я столкнулся, заключается в том, что если я поместил свой код инициализации для своих элементов управления в метод initWithCoder представления и привязку в awakeFromNib представления, привязка не подключается. Если я поместил инициализацию для своих элементов управления в awakeFromNib, когда нажата кнопка, у меня нет доступа к элементам управления в моем представлении (они имеют значение NULL при печати с использованием NSLog).

Из того, что я могу сказать, похоже, проблема заключается в том, что, как работает NSCollectionView, он создает экземпляр представления, а затем копирует его для того, как все много объектов находятся в представлении коллекции. Как получить инициализацию кнопок и привязку к работе с копией прототипа?

Ниже мой код инициализации и мой привязки в awakeFromNib для моего подклассы зрения:

SubView.h

@interface SubView : NSView { 
    NSButton *button; 
    NSTextField *textField; 
    IBOutlet NSCollectionViewItem *item; // Connected in IB to my NSCollectionViewItem 
} 

- (IBAction)buttonClicked:(id)sender; 

@end 

SubView.m

@implementation SubView 

- (id)initWithCoder:(NSCoder *)decoder 
{ 
    id view = [super initWithCoder:decoder]; 

    button = [[NSButton alloc] initWithFrame:NSMakeRect(50, 95, 100, 20)]; 
    [button setTitle:@"Begin Editing"]; 
    [button setTarget:self]; 
    [button setAction:@selector(buttonClicked:)]; 
    [self addSubview:button]; 

    textField = [[NSTextField alloc] initWithFrame:NSMakeRect(10, 10, 100, 75)]; 
    [self addSubview:textField]; 

    return(view); 
} 

- (void)awakeFromNib 
{ 
     // Bind the textField to the representedObject's name property 
     [textField bind:@"value" 
     toObject:item 
     withKeyPath:@"representedObject.name" 
     options:nil]; 
} 

- (IBAction)buttonClicked:(id)sender 
{ 
    [button setTitle:@"End Editing"]; 
    [textField setHidden:YES]; 
} 

@end 

ответ

12

Это похоже на то, что я только что сделал, поэтому, возможно, это то, что вам нужно.

Подкласс NSCollectionView и переопределение:

- (NSCollectionViewItem *)newItemForRepresentedObject:(id)object 

В newItemForRepresentedObject:, извлечь элемент просмотра, а затем добавить элементы управления и любые программные привязок:

@implementation NSCollectionViewSubclass 

- (NSCollectionViewItem *)newItemForRepresentedObject:(id)object { 

    // Allow the superclass to create or copy the collection view item 
    NSSCollectionViewItem *newItem = [super newItemForRepresentedObject:object]; 

    // Get the new item's view so you can mess with it 
    NSView *itemView = [newItem view]; 

    // 
    // add your controls to the view here, bind, etc 
    // 

    return newItem; 
} 

@end 

Надеюсь, это где-то рядом, где вам нужно be ...

-1

-awakeFromNib не вызывается для представлений скопирован из прототипа NSCollectionViewItem. Поместите свой код привязки в initWithCoder:, и все будет в порядке.

+0

права, когда я пытаюсь поставить мой код привязки в initWithCoder: Я получаю эту ошибку: непойманные исключения было поднято Контроллер не может быть nil *** Завершение приложения из-за неперехваченного исключения «NSInvalidArgumentException», причина: «Контроллер не может быть nil» Я думаю, что это потому, что свойство «item» (выход IB в CollectionViewItem) еще не создано подключен в initWithCoder. Есть ли другой способ доступа к представленному объекту? – Austin

+0

Hmm .. хорошо пункт. Вероятно, вашим лучшим решением было бы поместить код привязки в другой метод, а затем вызвать его с помощью -performSelector: withObject: afterDelay: 0.0. Это некрасиво, но это должно сработать, так как я не думаю, что есть альтернатива. – kperryua

+0

Я попытался вызвать код привязки с помощью функции performSelector: withObject: afterDelay из моего initWithCoder, но проблема в том, что initWithCoder вызывается, затем awakeFromNib, после чего initWithCoder вызывается для каждого элемента представления коллекции. Не могли бы вы изменить свой ответ, чтобы показать код привязки, который, по вашему мнению, должен работать? – Austin

1

-awakeFromNib не вызывается для представления для объекта NSCollectionViewItem, если это представление находится в th тот же nib, что и NSCollectionView, но вызывается, если вы поместите представление в отдельный наконечник.

  • Создайте пустой файл нибы (BlahBlahCollectionViewItem.nib).
  • Вырезать вид коллекции предмета из любого СИБА у вас в
  • Вставьте его в новый файл бобов
  • Измените класс своего владельца к NSCollectionViewItem.
  • Подключите выход вид на владельца вновь наклеенной зрения
  • Открыть файл СИБ, содержащий NSViewController
  • Выберите соответствующий NSViewControllerItem
  • Изменить его свойство Nib Name на имя нового наконечника пера
  • Храните код в -awakeFromNib