2009-07-31 3 views
4

Ich habe erfolgreich eine NSCollectionView erstellt und dem Ansichtsprototyp in IB eine Beschriftung hinzugefügt, die an eine Eigenschaft meines dargestellten Objekts gebunden ist. Ich möchte jetzt ein NSButton und NSTextField mit dem NSTextField programmatisch erstellen, das an eine Eigenschaft meines dargestellten Objekts gebunden ist. Wenn die Schaltfläche geklickt wird, möchte ich das NSTextField ein- und ausblenden.Wie binde ich programmatisch in der Sichtunterklasse meiner NSCollectionView?

Das Problem, das mir begegnet ist, wenn ich meinen Initialisierungscode für meine Steuerelemente in der InitWithCoder -Methode der Ansicht und die Bindung in der Ansicht watchFromNib der Ansicht, die Bindung wird nicht angeschlossen. Wenn ich die Initialisierung für meine Steuerelemente in die watchFromNib-Funktion lege, habe ich beim Klicken auf die Schaltfläche keinen Zugriff auf die Steuerelemente in meiner Ansicht (sie sind null, wenn sie mit NSLog ausgedruckt werden).

Von dem, was ich sagen kann sieht es aus wie das Problem möglicherweise, dass die Art, wie NSCollectionView funktioniert, eine Instanz der Ansicht erstellt und kopiert es dann für wie viele Objekte in der Sammlungsansicht sind. Wie bekomme ich die Schaltflächen zum Initialisieren und die Bindung mit der Kopie des Prototyps zu arbeiten?

Unten ist mein Code für die Initialisierung und meine im awakeFromNib für meine Unterklasse Ansicht Bindung:

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 

Antwort

12

Das klingt ähnlich wie etwas, das ich gerade gemacht habe, also ist es vielleicht das, was du brauchst.

Subclass NSCollectionView und Überschreibung:

- (NSCollectionViewItem *)newItemForRepresentedObject:(id)object 

In newItemForRepresentedObject:, die Ansicht Artikel retreive, dann Steuerelemente hinzufügen und keine programmatische Bindungen:

@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 

Hoffentlich ist irgendwo in der Nähe, wo Sie brauchen be ...

-1

-awakeFromNib ist nicht für die Ansichten genannt kopiert aus dem Prototyp NSCollectionViewItem. Setzen Sie Ihren Bindungscode in initWithCoder: und Sie sollten in Ordnung sein.

+0

rechts, wenn ich versuche, meine Bindung Code in initWithCoder zu setzen: ich bekomme diese Fehlermeldung: Eine abgefangene Ausnahme 01 angehoben wurdeController kann nicht Null sein *** Beenden App aufgrund der nicht abgefangenen Ausnahme 'NSInvalidArgumentException', Grund: 'Controller kann nicht Null' Ich denke, es ist, weil die "Element" -Eigenschaft (ein IB Outlet zu CollectionViewItem) noch nicht ist verbunden in initWithCoder. Gibt es eine andere Möglichkeit, zum reprodedObject zu gelangen? – Austin

+0

Hmm .. guter Punkt. Wahrscheinlich die beste Problemumgehung wäre, den Bindungscode in eine andere Methode zu schreiben und sie dann mit -performSelector aufzurufen: withObject: afterDelay: 0.0. Es ist nicht schön, aber es sollte funktionieren, da ich denke, dass es keine Alternative gibt. – kperryua

+0

Ich habe versucht, den Bindungscode mit dem performSelector aufzurufen: withObject: afterDelay von meinem initWithCoder, aber das Problem ist, dass der initWithCoder aufgerufen wird, dann wakeFromNib, dann initWithCoder wird für jede Sammlung View-Element aufgerufen. Können Sie Ihre Antwort ändern, um den verbindlichen Code anzuzeigen, der Ihrer Meinung nach funktionieren sollte? – Austin

1

-awakeFromNib wird in der Ansicht für ein NSCollectionViewItem nicht aufgerufen, wenn diese Ansicht in th ist Die gleiche Nib wie die NSCollectionView, aber es wird aufgerufen, wenn Sie die Ansicht in eine separate Nib setzen.

  • Erstellen Sie eine leere NIB-Datei (BlahBlahCollectionViewItem.nib).
  • die Ansicht Auflistelement Herausgeschnitten von was auch immer Spitze haben Sie es in
  • es in die neue NIB-Datei einfügen
  • Ändern der Klasse seines Besitzers zu NSCollectionViewItem.
  • Verbinden Sie die Ansicht Steckdose an den Eigentümer der neu eingefügten Ansicht
  • Öffnen Sie die Nib-Datei die NSViewController
  • Wählen Sie das dazugehörige NSViewControllerItem
  • Ändern seiner Nib Name-Eigenschaft auf den Namen der neuen Spitze
  • enthält
  • halten Sie Ihren Code in -awakeFromNib