ios

NSMenu dinamici

Ecco a voi il primo nerdpost al cacao.

Oggi parliamo infatti di un argomento nuovo per nerdammer.it ma che non può mancare: programmazione OSX/iOS , da Cocoa a CocoaTouch.

Iniziamo oggi con una esperienza Cocoa: la classe NSMenu.

In generale è sempre stato un Nib/Xib a trasportare nelle nostre applicazioni la struttura dei menu (grazie a InterfaceBuilder): ma quanti non hanno mai avuto bisogno di costruire un menu totalmente dinamico?

In una applicazione ben costruita l’approccio sarebbe subito quello di ricercare un controller specializzato, configurarlo con un eventuale modello e collegarlo (binding KVO) all’istanza di NSMenu che si intende dinamizzare: tutto risolvibile in IB.

Ebbene: niente di tutto questo è possibile! NSMenu non solo non ha un corrispondente controller specializzato (e va beh, l’avremmo costruito da soli, magari partendo da NSObjectController), ma non è neppure conforme al protocollo KVO/KVC !!!

In buona sostanza manca un metodo setItemArray reciproco del itemArray che nell’interfaccia consente la semplice visione dello status quo.

Infatti da sempre NSMenu è conforme ad un protocollo di delega (prima informale, poi introdotto in 10.6 con il protocollo formale NSMenuDelegate) simile al protocollo di data source.

Quindi come soluzione abbiamo solo la possibilità di costruire il nostro controller compatibile con tale protocollo e renderlo il delegato del menu da dinamizzare.

Rispondendo al messaggio:

- (void)menuNeedsUpdate:(NSMenu *)menu;

potremo modificare (removeItem, addItem, insertItem) la struttura del menu ogni volta sia necessario (e questo lo decide l’oggetto menu). Questo messaggio verrà infatti inviato dal menu (il cui puntatore è portato in argomento) all’oggetto delegato ogni volta che il menu dovrà essere visualizzato o aggiornato a schermo.

Se i tempi di costruzione dell’intero menu dovessero essere alti, è preferibile utilizzare la coppia di metodi:

- (NSInteger)numberOfItemsInMenu:(NSMenu *)menu;
- (BOOL)menu:(NSMenu *)menu updateItem:(NSMenuItem *)item atIndex:(NSInteger)index shouldCancel:(BOOL);

rispondendo ai quali potremmo consentire la ricostruzione anche parziale (ossia delle sole parti necessarie) del menu.
Il primo indica al menu di quante voci sia composto; il secondo consente di definire ciascuna voce (individuata per indice, considerando il menu affine ad un array di voci quale ci è presentato nel metodo itemArray).

Sostanzialmente questa interfaccia è rimasta invariata fino a 10.7 (Lion), pertanto è al momento l’unica possibilità di interagire dinamicamente con NSMenu senza riscrivere la sua implementazione.

Inutile quindi inerpicarsi in altre costruzioni: questo è il modo per dinamizzare un menu.

E che dire di implementate il metodo setItemArray in una categoria? Una ipotesi, che se concreta (potrebbe non rispondere a esigenze di performance) potremmo vedere in un prossimo post…

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *