Pagine

2012-04-17

Liberarsi della documentazione Xcode che non ci serve

Con l'ultimo aggiornamento di Xcode, Apple ha trasformato il tool di sviluppo in una sola applicazione, per rendere più semplice il processo di aggiornamento tramite Mac App Store. Per facilitare questa piccola grande transizione, già dalla versione precedente, era possibile scegliere quali componenti dovevano essere installati e scaricarli direttamente da dentro l'applicazione.


Il problema

La documentazione scaricata direttamente sull'hard disk, oltre ad offrire una velocità indubbiamente superiore al download, ne permette la visualizzazione anche in assenza di una connessione ad Internet. Tuttavia, anche se ormai le dimensioni degli hard drive odierni non pongono quasi più questo problema, può dar fastidio, ad uno sviluppatore che scrive applicazioni solo per Mac, trovare gigabyte occupati per la documentazione di ben due versioni di iOS (mi è ancora ignoto per quale motivo Xcode permetta di scaricare la documentazione di iOS 5.0 e quella di iOS 5.1: la seconda non dovrebbe essere un aggiornamento della prima?); allo stesso modo, a coloro che sviluppano solo per il sistema operativo mobile, non serve a nulla la documentazione di Mac OS X 10.7.

La soluzione

La prima cosa che può venire in mente a chiunque è: "perché non posso semplicemente cancellare la documentazione che non utilizzo da Xcode?". Purtroppo, chi ha già tentato questa vita, avrà già scoperto che l'applicazione, per quanto metta a disposizione un pulsante "-", lo tiene rigorosamente disabilitato se sono selezionate documentazioni che vengono installate di default.

Per fortuna, ci viene in aiuto un dettaglio che gli sviluppatori Apple hanno pensato di mettere, forse per farci un favore: facendo click sul pulsante nell'angolo sinistro della tabella (la sua figura rappresenta un rettangolo con una freccia dentro) verrà aperta una sezione, normalmente nascosta, dove vengono fornite ulteriori informazioni sulla libreria selezionata, tra cui anche il suo indirizzo sul nostro hard disk. A questo punto, non ci basterà che farvi click sopra per vederlo apparire nel Finder.

Metto a disposizione, qui di seguito, le posizioni di default dove vengono installate le librerie di iOS 5.0, iOS 5.1 e Mac OS X 10.7:

iOS 5.0 (557,4MB)
~/Library/Developer/Shared/Documentation/DocSets/com.apple.adc.documentation.AppleiOS5_0.iOSLibrary.docset 

iOS 5.1 (559,3MB)
~/Library/Developer/Shared/Documentation/DocSets/com.apple.adc.documentation.AppleiOS5_1.iOSLibrary.docset 

Mac OS X 10.7 (996,9MB)
/Library/Developer/Shared/Documentation/DocSets/com.apple.adc.documentation.AppleLion.CoreReference.docset 

Fate attenzione al fatto che, mentre la documentazione di iOS è situata nella Libreria dell'utente (simboleggiata dal carattere ~), quella di Mac OS X viene installata nella Libreria di sistema.

(Nota: su Mac OS X Lion e superiori, la cartella Libreria dell'utente è nascosta per default. Potete raggiungerla dal collegamento fornito da Xcode, oppure aprendo il menù Vai del Finder mentre si tiene premuto il tasto Option, e scegliendo la voce "Libreria")


Una volta selezionato il file che ci interessa, non dovremo far altro che spostarlo nel Cestino. Il Finder richiederà l'autorizzazione di un amministratore per eseguire tale operazione, ma una volta fornita la password, il file sarà spostato nel Cestino e sarà possibile eliminarlo.

Si consiglia di eseguire l'operazione di eliminazione mentre Xcode è chiuso. Nel caso in cui si desideri riaccedere alla documentazione cancellata, è possibile riscaricarla dal pannello "Downloads" delle Preferenze di Xcode.

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.