Introduzione
Nella lezione precedente abbiamo visto come specializzare un oggetto generico UIView, per rispondere alle nostre esigenze. In particolare, abbiamo creato un oggetto contenitore ed una serie di oggetti che, popolando il contenitore (UIView), hanno dato vita ad una calcolatrice.




L'aspetto interessante del nostro codice risiede nel fatto che tutta la logica di funzionamento e' stata associata alla classe CalculatorView di tipo UIView: il nostro contenitore calcolatrice.

Questo particolare design ci permettera' di effettuare un'ulteriore specializzazione del nostro codice, rendendo la nostra calcolatrice una app standard facente uso di un controllore, secondo il precedentemente citato modello MVC (Model-View-Controller).


UIViewController
Tipicamente, tutte le applicazioni che fanno uso dell'UIKit hanno almeno una UIWindow, allocata dal delegato della nostra applicazione, ed una o piu' UIViewController.
La classe UIViewController, fornisce il modello fondamentale di gestione delle view per le nostre applicazioni. Sebbene sia possibile renderizzare a schermo direttamente una UIView, quello che si fa' di solito e' delegare il compito del rendering a schermo della view ad una classe controllore.

UIViewController supporta la rappresentazione a schermo di una UIView associata, fornendo importanti primitive per la gestione dello schermo in relazione a cambiamenti di orientamento dell'apparato ( rotazione ) ed il supporto per views modali ( UIAlertSheet ed UIAlertView) .

Una istanza di UIViewController puo' essere utilizzata per gestire una view a tutto schermo. Per una semplice applicazione questo comporta gestire la view responsabile del contenuto della applicazione; per un'applicazione piu' complessa questo potrebbe comportare l'impiego di tecniche di switching di views, per rispecchiare il flusso logico dell'applicativo.




Ritornando all'esempio della lezione precedente, proveramo inizialmente ad incapsulare la nostra classe CalculatorView (UIView), all'interno di un controllore di viste (UIViewController). Successivamente proveremo a potenziare la nostra applicazione con nuove caratteristiche, sfruttando l'uso di ulteriori oggetti UIView specializzati in particolari mansioni.



Creazione di una UIViewController
Una UIViewController si comporta in maniera pressoche' analoga all'oggetto UIView che avevamo creato nello scorso esempio: essa contiene al suo interno un oggetto UIView.
Per prima cosa creiamo un nuovo progetto:




Diamo un nome significativo al nostro applicativo e scegliamo come template: Window-based Application. Dopo aver modificato opportunamento il file main.m ed eliminato i file di risorse superflui, procediamo alla creazione di una nuova classe per il nostro progetto. Scegliamo New dal menu File (Tasto Mela+N) e selezioniamo come tipologia di classe UIViewController.




Scegliamo come nome per la nuova classe CalculatorViewController. Quella appena generata sara' la classe responsabile della nostra applicazione: conterra' al suo interno un oggetto di tipo CalculatorView (UIView) e tutti i metodi necessaari per la corretta rappresentazione a schermo.

Apriamo il vecchio progetto e trasciniamo, selezionando e tenendo il tasto del mouse premuto, la classe CalculatorView dal vecchio al nuovo progetto:

drag...


...drop




Aggiungiamo un oggetto di tipo CalculatorView alla nostra dichiarazione di interfaccia: esso rappresenta la view gestita dal nostro controllore.



Ricordiamoci di aggiungere una forward declaration per la classe CalculatorView, altrimenti il compilatore non sapra' riconoscere correttamente la nuova classe introdotta.



loadView ed UIView
Selezioniamo la parte implementativa della nuova classe generata ( CalculatorViewController.m ). Il sistema genera per noi una quantita' abbondante di codice per la gestione della classe. Per ora non preoccupiamoci di tutti i metodi, cercheremo di focalizzarci su ognuno di essi non appena diverra' necessario per la corretta interpretazione del nostro codice.

Il metodo piu' importante da ricercare all'interno del codice autogenerato e':

// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView {
...



Quando viene creato un nuovo UIViewController, viene effettuata una chiamata al suo metodo loadView. Sara' responsabilita' del programmatore scrivere tutto il codice necessario alla corretta creazione della classe UIView da associare al nostro controllore.

La classe UIViewController crea automaticamente un oggetto UIView durante la sua fase di inizializzazione. Quest'oggetto sara' la view di default del nostro controllore e sara' possibile accedervi attraverso la properties self.view. Quando creiamo il nostro oggetto UIView abbiamo due possibilita': ancorarlo all'oggetto esistente:

- (void)loadView {
  ...
  ...
  [self.view addSubview:some_other_view];
  ...
  ...
}



oppure, sovrascriverlo:

- (void)loadView {
  ...
  ...
  self.view = some_other_view;
  ...
  ...
}



Visto che abbiamo creato in precedenza una nostra classe UIView custom di nome CalculatorView, seguiremo il secondo metodo. Ecco come apparira' il nostro metodo loadView:



Abbiamo ricavato la dimensione dell'applicationFrame attraverso il corrispondente messaggio di istanza all'oggetto UIScreen. Ottenute le informazioni necessarie al corretto posizionamento della nostra UIView, possiamo procedere con l'allocazione ed inizializzazione del corrispondente oggetto CalculatorView; la sua istanza verra' utilizzata per sovrascrivere la property self.view del nostro oggetto controllore. Non dimentichiamo, infine, di rilasciare la memoria: l'assegnazione della nostra istanza alla property view, infatti, aumenta correttamente il contatore di memoria responsabile della deallocazione di ogni oggetto presente nella nostra applicazione.

L'altro metodo importante per quest'esempio e' quello che si riferisce alla deallocazione della nostra classe: dealloc.



Come si puo' vedere, non dobbiamo deallocare nessun oggetto. L'oggetto myCalculatorView, infatti, viene gia' rilasciato in fase di inizializzazione nel metodo precedente. L'unica cosa che dovra' fare il nostro metodo di deallocazione, quindi, sara' lanciare un messaggio analogo di dealloc alla classe padre (UIView).



AppDelegate e ViewController
Dobbiamo adesso riportare queste modiche sulla nostra classe delegato. CalculatorAppDelegate dovra' rispecchiare la nuova logica dell'applicazione: contenere un riferimento al controllore di vista (UIViewController) e niente altro.

Sara' la classe UIViewController ad occuparsi della visualizzazione a schermo della UIView e della sua gestione. La classe CalculatorView, invece, si occupera' della logica dell'applicazione.




Ricordiamo che il primo metodo che interviene alla fine dell'inizializzazione della nostra applicazione in memoria e' applicationDidFinishLaunching, gestito dalla nostra classe delegato.

Esso dovra' preoccuparsi di creare un oggetto UIWindow atto a contenere la nostra UIView. Dovremo, inoltre, istanziare la nostra classe UIViewController, responsabile di tutti i dettagli necessari alla corretta gestione dello schermo e delle viste.




Il messaggio di addSubview: verra' modificato per ospitare l'oggetto referenziato dalla properties view del nostro controllore. Ricordiamo che nel metodo loadView istanziamo una classe CalculatorView.

Visto che non abbiamo referenziato direttamente l'oggetto controllore - nella chiamata ad addSubview: interviene la properties view e non l'istanza di UIViewController - non possiamo rilasciare la sua memoria. Sara' la classe dealloc ad occuparsi del corretto rilascio della memoria.






Riferimenti

- Mac OS X Reference Library: iPhone Application Programming Guide
- Mac OS X Reference Library: Window and Views
- Programming in Objective-C - Capitolo 7
- Programming in Objective-C - Capitolo 8
- iPhone SDK Application Development - Capitolo 3



    lap1

downloads