2011-12-13 18 views
9

Esiste un tipo di ID che può essere utilizzato e impostato in .nib/.xib tramite Xcode che può essere interrogato in fase di runtime per identificare una particolare istanza di visualizzazione dal codice?ID univoco su NSViews

In particolare, quando si dispone di più copie della stessa sottoclasse NSView nella nostra interfaccia, come possiamo dire quale è attualmente in esame?

risposta

9

Gli oggetti generici NSView non possono avere la loro proprietà tag impostata in Interface Builder. Il metodo tag su NSView è un metodo di sola lettura e può essere implementato solo in sottoclassi di NSView. NSView non implementa un metodo setTag:.

ho il sospetto le altre risposte si riferiscono a casi di NSControl che definisce un metodo -setTag: e ha un campo di Interface Builder per consentire di impostare il tag.

Cosa si può fare con viste generiche è utilizzare attributi di runtime definiti dall'utente. Ciò consente di preimpostare i valori delle proprietà nell'oggetto della vista. Quindi, se la visualizzazione definita una proprietà in questo modo:

@property (strong) NSNumber* viewID; 

Poi nella sezione definita dall'utente attributi della finestra di ispezione identità in Interface Builder, è possibile aggiungere una proprietà con il percorso chiave viewID, il tipo di Number e il valore 123 .

Nel metodo -awakeFromNib della vista dell'utente, è possibile accedere al valore della proprietà. Nell'esempio sopra riportato, la proprietà viewID della vista sarà stata preimpostata su 123.

+0

Sembra fantastico, grazie per il suggerimento! Ci proverò. Ahimè, niente di pre-definito nella vaniglia Cocoa NSView che può essere usato ma immagino che sto ancora pensando troppo in un modo PowerPlant/MFC ;-) – Jay

+1

La risposta qui sotto funziona per una vista generica. Basta impostare Identifer in xib e accedervi a livello di codice con view.identifier – Colin

+0

Qualche idea su quale logica dietro il tag sia in sola lettura in NSView? – Mercurial

10

In Interface Builder, c'è un modo per impostare "identificatore" di un NSView. In questo caso, userò l'identificatore "54321" come stringa identificatore.

NSView Conforme allo NSUserInterfaceItemIdentification Protocol, che è un identificatore univoco come NSString. Si può camminare nella gerarchia della vista e trovare NSView con quell'identificatore.

Quindi, per costruire su questo post su come ottenere l'elenco dei NSViews, Get ALL views and subview of NSWindow, si potrebbe quindi trovare il NSView con l'identificatore che si desidera:

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification 
{ 
    NSView *viewToFind = [self viewWithIdentifier:@"54321"]; 
} 

- (NSView *)viewWithIdentifier:(NSString *)identifier 
{ 
    NSArray *subviews = [self allSubviewsInView:self.window.contentView]; 

    for (NSView *view in subviews) { 
     if ([view.identifier isEqualToString:identifier]) { 
      return view; 
     } 
    } 

    return nil; 
} 

- (NSMutableArray *)allSubviewsInView:(NSView *)parentView { 

    NSMutableArray *allSubviews  = [[NSMutableArray alloc] initWithObjects: nil]; 
    NSMutableArray *currentSubviews = [[NSMutableArray alloc] initWithObjects: parentView, nil]; 
    NSMutableArray *newSubviews  = [[NSMutableArray alloc] initWithObjects: parentView, nil]; 

    while (newSubviews.count) { 
     [newSubviews removeAllObjects]; 

     for (NSView *view in currentSubviews) { 
      for (NSView *subview in view.subviews) [newSubviews addObject:subview]; 
     } 

     [currentSubviews removeAllObjects]; 
     [currentSubviews addObjectsFromArray:newSubviews]; 
     [allSubviews addObjectsFromArray:newSubviews]; 

    } 

    for (NSView *view in allSubviews) { 
     NSLog(@"View: %@, tag: %ld, identifier: %@", view, view.tag, view.identifier); 
    } 

    return allSubviews; 
} 

Oppure, dal momento che si sta utilizzando una sottoclasse NSView, è potrebbe impostare il "tag" di ogni vista in fase di esecuzione. (Oppure, è possibile impostare l'identificatore in fase di esecuzione.) La cosa bella del tag, è che esiste una funzione predefinita per trovare una vista con un tag specifico.

// set the tag 
NSInteger tagValue = 12345; 
[self.myButton setTag:tagValue]; 

// find it 
NSButton *myButton = [self.window.contentView viewWithTag:12345];