Pagine

2012-04-02

Quando il PopUp cambia

Come reagire ad un cambio della selezione di un menu popup?
La cosa è piuttosto semplice, ma spesso me la dimentico, per cui ora la inserisco qui sul blog!
Non parlo dei popup costruiti direttamente nell'Interface Builder, ma di quelli costruiti dinamicamente da codice.
Per prima cosa, occorre introdurre un NSArrayController, che conterrà i valori che saranno presenti nel menu del popup. Tali valori possono trovarsi in un file plist, in modo da essere caricati all'inizio (p.es. nel metodo AwakeFromNib) o generati direttamente da codice con il metodo AddObject dell'ArrayController.
Creiamo un ArrayController nel nib, scegliendolo nella libreria dell'Interface Builder e trascinandolo nel nib, come al solito. È conveniente dargli un nome specifico, giusto per poterlo distinguere facilmente.
Poi nell'header del nostro oggetto (nel seguito supponiamo che sia il delegate dell'applicazione) creiamo un Outlet:
IBOutlet NSArrayController *myArrayCtrl;
Selezioniamo il nib, facciamo un ctrl-drag dall'icona dell'arrayController al delegate e dal menu che ne esce scegliamo myArrayCtrl: abbiamo quindi unito il controller all'outlet del delegate.
Inserendolo nel nib e legandolo all'Outlet, siamo sicuri che venga creato; se così non fosse, dovremmo crearlo noi per esempio nel metodo init.
Ora selezioniamo il menu popup che avremo aggiunto, andiamo nell'inspector dei bindings, sulla destra dell'Xcode e leghiamo le seguenti property dei popup ai corrispondenti percorsi del controller:

content → myArrayCtrl.arrangedObjects
selectedIndex → myArraCtrl.selectionIndex


Se l'array contiene un NSDictionary, collegheremo anche

contentValues → myArrayCtrl.arrangedObjects.theName

avendo supposto che la chiave theName contenga quello che vogliamo compaia nel menu.
Nell'Interface Builder abbiamo finito; ora andiamo nel .m del delegate; in un metodo di inizio (p.es. awakeFromNib oppure applicationDidFinishLaunching) dobbiamo registrare il delegate come osservatore della chiave selectionIndex:
 
[myArrayCtrl addObserver:self forKeyPath:@"selectionIndex" options:NSKeyValueObservingOptionNew context:nil];
 
Il valore NSKeyValueObservingOptionNew ci mette in condizioni di conoscere il nuovo valore.
Ora il delegate sta in ascolto delle variazioni cercate, ma occorre che sappia rispondere al metodo
 
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
 
Tutte le volte che il popup cambia selezione (quindi nessuna chiamata se viene soltanto aperto e rilasciato senza cambiare), viene chiamato questo metodo: nella sua implementazione potremo decidere cosa fare quando la selezione cambia.
Da notare che la chiamata avviene per qualunque oggetto la cui chiave selectionIndex è cambiata: quindi, se abbiamo altri observer sul selectionIndex dovremo controllare nel codice del metodo se si tratta del nostro popup: in questo caso l'oggetto object nel NSDictionary *change sarà contenuto il nuovo valore; questo ci permette di monitorare più di un menu e prendere decisioni diverse. In caso di necessità, possiamo settare l'oggetto context nell'AddObserver, in modo che nel metodo possiamo controllare se la situazione è quella voluta: per esempio, potremmo far scattare l'azione solo se il menu è cambiato in una certa condizione e non far nulla negli altri casi.

Nessun commento:

Posta un commento