Seguendo il tutorial di Apple costruiamo questo piccolo software che permette di convertire il valore di una moneta in un altra attraverso il suo tasso di cambio. Ovviamente trovate il tutorial nella documentazione di xcode in inglese, io qui non faccio una mera traduzione ma seguo il percorso e faccio le mi belle osservazioni. Vi consiglio nel seguire il tutorial di non copiare ed incollare il codice Obj-C ma di scriverlo così da capirlo e memorizzarlo meglio.
Per prima cosa bisogna aprire xcode e creare un nuovo progetto partendo dal menu File > New Project.
Nella finestra che contiene alcuni tipi di progetto pre-impostati scegliete Cocoa Application, non selezionate alcuna opzione e cliccate sul pulsante choose…
Vi verrà chiesto di salvare il progetto, inserite il nome Currency converter, scegliete una posizione idonea e salvate. Dovreste ora visualizzare una finestra simile a questa in figura.

Schermata - xcode
Il passo successivo e creare l’oggetto Model della nostra applicazione. Come abbiamo visto nell’articolo su MVC, l’oggetto Model rappresenta i dati e le azioni che si posso fare su di essi. Nella programmazione ad oggetti, l’oggetto non è altro che una istanza di una classe. Dobbiamo quindi creare una nuova classe nel nostro progetto. Per far ciò selezioniamo la cartellina Classes nella colonna di destra della finestra principale di xcode e poi menu File > New file… o semplicemente mela N. Si apre ancora un wizzard che ci permette di scegliere che tipo di file vogliamo aggiungere al nostro progetto. Scegliamo il modello Objective-C Class nel gruppo cocoa class e scegliamo NSObject nel menu a tendina subclass of. Prossimamente vedremo bene che cosa significa sottoclasse, per ora ci basta sapere che cocoa mette a disposizione una classe padre, NSObject appunto, che fornisce tutto quello che serve per creare e gestire un oggetto nell’ambiente cocoa. Derivando la nostra classe da NSObject, essa erediterà tutte le caratteristiche di NSObject. In Obj-c, nella gerarchia delle classi, può esistere una sola classe padre genitrice di tutte le altre. Benché sia possibile in Cocoa creare una classe padre, di fatto esiste appunto NSObject che svolge questo compito egregiamente rendendo superfluo lo sviluppo di un’altra classe padre. Questo concetto è comunque alla base della programmazione ad oggetti, se non lo conoscete occorre una pausa per capirlo bene legendo un pò di documentazione al riguardo.
Bene clicchiamo su next e nella successiva schermata specifichiamo il nome della nostra classe: Converter. Clicchiamo su Finish, xcode aggiungerà due file nel gruppo Classes: l’interfaccia converter.h e l’implemtazione converter.m . Perché due file? Vediamolo!
In Objective C una classe è composta da 2 elementi principali:
- Una interfaccia dove vengono dichiarate le variabili, le proprietà e i metodi della classe cioè le funzioni che operano sui dati. L’interfaccia della classe si scrive nel file .h.
- Un’ implementazione, cioè il codice vero e proprio che esegue le azioni sui dati. L’implementazione della classe si scrive nel file .m
La programmazione ad oggetti ha svariati vantaggi fra questi la possibilità di creare e riutilizzare i singoli oggetti sapendo soltanto cosa essi fanno e non come lo fanno. L’interfaccia serve a proprio a questo, a dirci cosa fa una certa classe! L’implementazione invece ci dice come fa una certa cosa quella classe ma questo nell’utilizzo dell’oggetto è ininfluente. Infatti nel normale utilizzo di un oggetto il suo contenuto rimane incapsulato al suo interno e noi accediamo ai suoi dati attraverso i metodi e le proprietà. Di fatto possiamo utilizzare oggetti implementati da altri senza conoscerne l’implementazione ma soltanto l’interfaccia. Ad esempio, in Cocoa, useremo spesso la Classe NSString che, istanziata, crea un oggetto adatto a manipolare una stringa senza conoscerne affatto l’implementazione. Dunque, benché sia possibile scrivere interfaccia e implementazione nello stesso file, è opportuno separarli in due file, .h e. m appunto, per separare i due concetti perché è appunto sufficiente l’interfaccia per conoscere ed usare la classe. Ci sono anche altri vantaggi ma per questi vi rimando a studi più approfonditi sulle classi.
Tornando al nostro tutorial apriamo il file converter.h e iniziamo a scrivere l’interfaccia del nostro oggetto model.
Notiamo che Xcode ha già fatto qualcosa per noi infatti troviamo già il seguente codice:
#import <Cocoa/Cocoa.h>
@interface Converter : NSObject {
}
@end
Come possiamo vedere, poiché abbiamo dichiarato che la nostra classe è figlia di NSObject, xcode ha prontamente inserito la direttiva necessaria per includere le classi Cocoa:
#import <Cocoa/Cocoa.h>
Da notare che la direttiva #import dell’ Ojective-C a differenza di quella #include nel C include il file solo se non è stato già incluso, forte no!
Xcode ha poi dichiarato già la nostra interfaccia attraverso la direttiva @interface, ogni dichiarazione di interfaccia in Objective-C inizia con @interface e finisce con @end
La dichiarazione come vediamo ha la seguente sintassi:
@interface NomeClasse : ClasseGenitrice { dichiarazione delle variabili }
Il nostro oggetto Model è piuttosto semplice poiché è costituito da un una classe “Converter” da due variabili, una con la cifra da convertire e una con il tasso di cambio, entrambe di tipo float e da un solo metodo convertCurrency che moltiplica la cifra da convertire per il tasso di cambio e torna il risultato.
Per prima cosa dichiariamo le due variabili, tale dichiarazione va fatta all’interno delle parentesi graffe!
float sourceCurrencyAmmount, rate;
Come vedete uso gli stessi nomi del tutorial sulla documentazione Apple, così da poter confrontare e approfondire con la documentazione originale. Il nostro Converter.h si presenta così ora:
#import <Cocoa/Cocoa.h>
@interface Converter : NSObject {
float sourceCurrencyAmount, rate;
}
@end
Le variabili dichiarate all’interno di una classe sono private, cioè sono utilizzabili solo dal codice all’interno della stessa. E’ necessario quindi definire dei metodi per poter accedere a queste variabili dall’esterno. Questi metodi sono i così detti getter e setter. In Obj-c 2.0 esiste una scorciatoia per definire tali metodi: dichiarare delle Property. Dichiarando una proprietà il compilatore creerà automaticamente il metodi getter e setter per quella proprietà. Una proprietà si dichiara così:
@property(attributi) Tipo listaNomiVariabili;
Gli attributi definisco il modo in cui si può accedere alla proprietà, essi possono essere readwrite, readonly, copy etc, vi consiglio di vedere la guida The Objective-C 2.0 Programming Language. Per ora ci basti sapere che senza specificare gli attributi, o specificando soltanto l’attributo readwrite il compilatore creerà soltanto i metodi getter e setter utilizzando i nomi nomeProperty per il getter e setNomeProperty per il setter.
Poiché vogliamo accedere alle nostre variabili dichiariamo due property, tale dichiarazione va fatta subito dopo la chiusura delle parentesi graffe.
@property(readwrite) float sourceCurrencyAmount, rate;
Con questa dichiarazione abbiamo di fatto dichiarato anche metodi
- (float)sourceCurrencyAmount;
- (void)setSourceCurrencyAmount:(float)newSourceCurrencyAmount;
- (float)rate;
- (void)setRate:(float)newRate;
Bel risparmio no! con una riga s’è scritto l’equivalente di 4!
Se vi state chiedendo come si dichiara un metodo vi accontento subito dichiarando l’unico metodo della nostra classe
- (float) convertCurrency;
Tale dichiarazione va inserita subito dopo quella delle proprietà, come vedete la dichiarazione dei metodi deve iniziare con un segno – seguita dal tipo restituito tra parentesi tonde e dal nome del metodo.
- (tipoRestituito) nomeMetodo
Il segno meno è obbligatorio ed indica che il metodo è un metodo di istanza, cioè un metodo che può essere chiamato su una istanza (oggetto) della classe. I metodi di classe invece vengono dichiarati con il segno +, questi sono metodi che vengono eseguiti dalla classe prima che questa venga istanziata. Un esempio di metodo di classe potrebbe essere il metodo che si occupa di riservare la porzione di memoria idonea a contenere il nostro oggetto. Se vi state chiedendo se la nostra classe ha bisogno di questi metodi la risposta è certamente si tuttavia non abbiamo bisogno di dichiarali a quanto pare. Non ne sono ancora sicuro al momento ma secondo me c’entra NSObject!!!
La dichiarazione del metodo prosegue con il tipo restituito messo tra parentesi tonde e il nome del metodo. Se un metodo non restituisce nulla occorre specificare void come tipo restituito.
Con la dichiarazione del metodo la nostra interfaccia è completa e dovrebbe mostrarsi così:
#import <Cocoa/Cocoa.h>
@interface Converter : NSObject {
//dichiarazione delle variabili
float sourceCurrencyAmount, rate;
}
//dichiarazione delle proprietà
@property(readwrite) float sourceCurrencyAmount, rate;
//dichiarazione dei metodi
- (float) convertCurrency;
@end
possiamo salvare il file Converter.h e passare all’implementazione della classe nel file Converter.m
Anche in questo caso Xcode ha già fatto qualcosa per noi come vedete il file converter.m si presenta così:
#import "Converter.h"
@implementation Converter
@end
Questo ci fa capire subito alcune cose, nel file .m è necessario importare il relativo file .h (mi sembra ovvio ma è meglio ripeterlo), similmente all’interfaccia anche l’implementazione incomincia con la direttiva
@implementation NomeClasse
e termina con la direttiva
@end
Tutto il codice di implementazione va inserito fra queste due direttive.
La prima cosa da fare è istruire il compilatore sulle due property che abbiamo dichiarato. L’ istruzione:
@synthesize listaNomiPorpertys
dice al compilatore di creare i metodi getter and setter per le proprietà specificate quindi:
@synthesize sourceCurrencyAmount, rate;
Anche in questo caso il risparmio di codice è notevole non dovendo implementare ben 4 metodi. L’istruzione @synthesize creerà questi metodi soltanto se non sono stati implementati, questo significa che se abbiamo esigenze d’ implementazione particolari per uno dei metodi getter e setter possiamo sempre farlo manualmente anche se abbiamo dichiarato la variabile come property!
Dobbiamo ora implementare il metodo convertCurrency che abbiamo dichiarato:
- (float) convertCurrency {
//il metodo ritorna la moltiplicazione delle due variabili
return self.sourceCurrencyAmount * self.rate;
}
Come vedete il metodo è semplicissimo, notiamo l’uso di self che in sostanza indica di utilizzare il valore della variabile interna all’oggetto. L’istruzione return ritorna il valore della moltiplicazione alla sua destra.
Il mio converter.m si mostra esattamente così:
#import "Converter.h"
@implementation Converter
//implemento le property
@synthesize sourceCurrencyAmmount, rate;
//implemento currencyConvert
- (void) currencyConvert {
return self.sourceCurrencyAmmount * self.rate;
}
@end
Ok si conclude qui la prima parte del tutorial, nella seconda ci occuperemo di creare l’interfaccia grafica con interface builder e di collegarla alla nostra classe. Chiedo scusa per le eventuali imprecisioni e/o omissioni, accetto ben volentieri correzioni, critiche e consigli e tenete presente che questi sono perlopiù appunti che sto prendendo io nello studio di cocoa che non hanno la pretesa di insegnare qualcosa a qualcuno.
Ciao
Commenti recenti