Diventare Un XCoder - Xcode 4
Diventare Un XCoder - Xcode 4
Titolo originale
Become an Xcoder Copyright © 2008 by Bert Altenburg, Alex Clarke and Philippe Mougin.
Version 1.15
Autori :
Bert Altenburg, Alex Clarke and Philippe Mougin - http://www.cocoalab.com
Edizione Italiana
Xcodeitalia - http://www.xcodeitalia.com
Licenza
Attribuzione :
Devi attribuire la paternità dell'opera nei modi indicati dall'autore o da chi ti
ha dato l'opera in licenza e in modo tale da non suggerire che essi avallino te o
il modo in cui tu usi l'opera.
Non Commerciale :
Non puoi usare quest'opera per fini commerciali.
Alessandro (alessandro)
Daniel (dr.got)
Davide (dave)
Fabrizio (fabrizioromeo)
Gino (lagmac)
Manuel (jekrom)
Marco (Ender)
Marco (iMArCo)
Riccardo (rickibrucelee)
Sandro (sandro.vandoni)
Simone (hrs)
Stefano (Stefano1983)
indice generale i
Indice generale
Capitolo 03 - Funzioni 16
Introduzione 16
La funzione main() 16
La nostra prima funzione 17
Passere degli argomenti 18
Restituire valori 20
Far funzionare il tutto 21
Variabili protette 23
ii Diventare un Xcoder
Variabili istanziate 52
Metodi 52
Oggetti in memoria 52
Esercizio - La nostra applicazione 53
Esercizio - La nostra prima classe 54
Esercizio - Creiamo il progetto 56
Esercizio - Creiamo la GUI 56
Esercizio - Esploriamo Interface Builder 58
Esercizio - Classe background 58
Esercizio - Custom classes 59
Esercizio - Una classe per controllare tutte le altre 60
Esercizio - Creiamo la nostra classe 60
Esercizio - Creare un’istanza in Interface builder 62
Esercizio - Creiamo le connessioni 63
Esercizio - Generare il codice 67
Esercizio - Pronti a ballare? 70
Capitolo 10 - awakeFromNib 78
Introduzione 78
Esercizio 78
Capitolo 11 - Puntatori 82
Introduzione 82
Referenziare variabili 82
Usare i puntatori 83
Capitolo 12 - Stringhe 86
Introduzione 86
NSString 86
ii Diventare un Xcoder
Il simbolo @ 87
Un uovo tipo di stringhe 87
Esercizio 87
NSMutableString 88
Esercizio 88
Ancora puntatori 90
Capitolo 13 - Arrays 94
Introduzione 94
Una “class method” 95
Esercizio 96
Conclusioni 98
Più efficiente sei con il tuo Mac, più è facile che le altre persone considerino un
Mac. Quindi, cerca di stare aggiornato visitando siti “Mac-oriented” e leggi
riviste Mac. Certamente, impara Objective-C o AppleScript e mettiti ad usarlo
in grande. Per i tuoi business, l'uso di AppleScript può farti risparmiare molti
soldi e tempo. Guarda il libretto gratuito di Bert "AppleScript for Absolute
Starter", disponibile su:
http://www.macscripter.net/books
Mostra al mondo che non tutti usano un PC rendendo così Macintosh più
visibile.
Indossare semplici T-shirt Mac in pubblico è uno dei modi, ma ce ne sono altri
per rendere Mac ancora più visibile da casa tua. Se si esegue Activity Monitor
(nella cartella Utility, che si trova nella cartella Applicazioni sul vostro Mac),
noterete che il vostro Mac utilizza tutta la sua potenza di elaborazione solo
occasionalmente. Gli scienziati hanno iniziato diversi progetti di calcolo
distribuito (DC) come ad esempio Folding@home o SETI@home, che sfruttano
la potenza di calcolo non sfruttato, solitamente per il bene comune.
http://distributedcomputing.info/projects.html
Introduzione
Quando impari a guidare una macchina, hai bisogno d'imparare a gestire più
cose contemporaneamente. Per questo a scuola guida ti spiegano tutto sul
funzionamento di un'autovettura prima di provare a fartela guidare.
Nello stesso modo, anche programmare richiede di conoscere alcune cose prima
d'iniziare, altrimenti il tuo programma non funzionerà, in termine tecnico
“andrà in crash”, così come in macchina se non sai qual è il pedale del freno
inevitabilmente andrai a sbattere.
Affinché non ti senta disorientato, lasciamo l'ambiente di programmazione per
un capitolo successivo. Inizieremo invece col farti familiarizzare con il linguaggio
Objective-C, spiegando alcune regole matematiche basilari che sicuramente ti
saranno familiari.
Alla scuola elementare hai imparato come fare i calcoli, compilando i puntini:
2 + 6 = ...
... = 3 * 4
Alle medie, i puntini sono andati fuori moda e le variabili chiamate x e y (e una
nuova parola di fantasia “algebra”) sono state aggiunte.
2 + 6 = x
y = 3 * 4
Variabili
Anche Objective-C usa le variabili. Le variabili non sono altro che nomi
convenienti per riferirsi a specifici dati, come ad esempio numeri. Ecco uno
statement di esempio in Objective-C, una linea di codice che assegna ad una
variabile un particolare valore. [1]
//[1] x = 4;
Un programma è una serie di istruzioni 4
Il punto e virgola
La variabile chiamata x ha preso il valore quattro.
Se presti attenzione alla fine della riga c'è un punto e virgola; questo è richiesto
alla fine di ogni statement. Perché è richiesto che ci sia un punto e virgola?
Il codice dell'esempio [1] può sembrarti stupido, ma un computer non sa cosa
farne. Un programma speciale, chiamato compilatore, è necessario per convertire
il testo che tu scrivi in una sequenza di zero e uno comprensibili per il tuo Mac.
Leggere e capire del testo scritto da un umano è molto difficile per un
compilatore, così tu devi fornirgli alcuni indizi, per esempio dove un particolare
statement finisce. Questo è quello che fa il punto e virgola, indica al compilatore
dove un determinato statement finisce.
Se ti dimentichi anche un singolo punto e virgola, il codice non può essere
compilato, e trasformato in qualche cosa di comprensibile dal tuo Mac.
Non ti preoccupare troppo di questo adesso, perché come vedremo più avanti, il
compilatore si lamenterà se non riuscirà a compilare il tuo codice e ti aiuterà a
trovare che cos'è sbagliato.
Nominare le variabili
Mentre i nomi delle variabili non hanno un significato particolare per il
compilatore, usare invece nomi descrittivi, rende un programma più semplice da
leggere e capire per noi. Questo è un grande vantaggio se abbiamo bisogno di
cercare un errore nel codice.
Gli errori nei programmi sono tradizionalmente chiamati bugs. Trovarli e correggerli
è chiamato debugging.
//[2] pictureWidth = 8;
Diventare un Xcoder
5 Capitolo 01
Significa che egli capisce se usi lettere maiuscole o no. Il nome della variabile
pictureWidth non è lo stesso di pictureWIDTH o di PictureWidth.
Seguendo le convenzioni generali, io creerò i nomi delle mie variabili fondendo
alcune parole, la prima senza maiuscole e facendo iniziare le altre parole che
formano la variabile con la lettera maiuscola, così come puoi vedere nell'esempio
[2]. Questo stile viene solitamente chiamato camelCase. Seguendo questo schema
ho ridotto gli errori di programmazione dovuti al case-sensitive in maniera
drastica.
Nota che il nome di una variabile è sempre una parola unica (o un singolo
carattere).
Mentre hai molta libertà nella scelta del nome, ci sono alcune regole alle quali un
nome di variabile dev'essere conforme. Quest'elenco potrebbe essere noioso. La prima
regola alla quale devi obbedire è che i nomi delle variabili non possono essere parole
riservate di Objective-C (una parola che ha un significato speciale per Objective-C).
Componendo il nome di una variabile con parole concatenate come pictureWidth sei
sempre al sicuro. Mantenere il nome della variabile leggibile, l'uso delle maiuscole
con i nomi delle variabili è raccomandato. Se ti attieni a questo schema, avrai un
numero di errori (bug) inferiore nei tuoi programmi. Se vuoi continuare ad imparare
ancora un paio di regole, finisci questo paragrafo. Oltre alle lettere, l'uso dei numeri è
consentito, ma al nome di una variabile non è permesso d'iniziare con un numero. È
consentito anche il carattere di underscore “_”. Ora alcuni esempi di nome di
variabile.
! Permessi:
! door8k
do8or
!
! Non permessi:
! door 8 (contiene uno spazio)
! 8door (inizia con un numero)
! Sconsigliati:
! Door8 (inizia con lettera maiuscola)
Un programma è una serie di istruzioni 6
//[3]
pictureWidth=8;
pictureHeight=6;
pictureSurfaceArea=pictureWidth*pictureHeight;
Sorprendentemente il compilatore non dice nulla sugli spazi (ad eccezione dei
nomi delle variabili, delle parole chiave, etc..). Quindi per rendere il codice più
leggibile possiamo usarli. [4]
//[4]
pictureWidth = 8;
pictureHeight = 6;
pictureSurfaceArea = pictureWidth * pictureHeight;
//[5]
pictureWidth = 8; //[5.1]
pictureHeight = 4.5; //[5.2]
pictureSurfaceArea = pictureWidth * pictureHeight;
I numeri in genere possono essere distinti in due tipi: numeri interi e numeri
decimali, di cui puoi vederne un esempio negli statement [5.1] e [5.2].
Gli interi sono usati per i conteggi, tipo quando avremo da ripetere una serie
d'istruzioni un numero specifico di volte (vedi capitolo 7). Conosci i numeri
decimali o a virgola mobile, per esempio, nel baseball le medie delle battute.
Diventare un Xcoder
7 Capitolo 01
//[6]
int pictureWidth; //[6.1]
float pictureHeight, pictureSurfaceArea; //[6.2]
pictureWidth = 8;
pictureHeight = 4.5;
pictureSurfaceArea = pictureWidth * pictureHeight;
Nella linea [6.1], int indica che la variabile pictureWidth è un intero. Nella linea
successiva [6.2], dichiariamo due variabili in una volta, separando i nomi con
una virgola e nello specifico, indica che entrambe le variabili sono di tipo float,
ovvero numeri che contengono parti decimali.
In questo caso è un po' sciocco che pictureWidth sia di un tipo differente dalle
altre due variabili.
Quello che non sai è che se moltiplichi un int con un float il risultato del
calcolo è un float; ecco perché devi dichiarare la variabile pictureSurfaceArea
come un float [6.2].
Perché il compilatore vuole conoscere quando una variabile rappresenta un
intero o un numero con parte decimale?
Un programma ha bisogno di una parte della memoria del computer. Il
compilatore riserva memoria (byte) per ogni variabile che incontra. Poiché
differenti tipi di dati, in questo caso int e float, richiedono differenti quantità di
memoria e diversa rappresentazione, il compilatore deve riservare la corretta
quantità di memoria e usare la giusta rappresentazione.
//[7]
unsigned int chocolateBarsInStock;
//[8]
int x = 10;
float y = 3.5, z = 42;
Tipi di dati
Come abbiamo appena visto, i dati memorizzati in una variabile possono essere
di diverso tipo, per esempio int o float.
In Objective-C, semplici tipi di dati come questi sono anche conosciuti come
dati scalari.
Nella tabella seguente una lista dei più comuni disponibili in Objective-C.
Diventare un Xcoder
9 Capitolo 01
Operazioni matematiche
Negli esempi precedenti abbiamo eseguito un'operazione di moltiplicazione.
Per eseguire le altre operazioni matematiche di base, devi usare i seguenti
simboli, conosciuti ufficialmente come operatori.
+ per l’addizione
- per la sottrazione
/ per la divisione
* per la moltiplicazione
Usando gli operatori, siamo in grado di eseguire una vasta gamma di calcoli. Se
si dà un'occhiata al codice dei programmatori professionisti in Objective-C,
t'imbatterai in un paio di peculiarità. Invece di scrivere x = x + 1 il
programmatore spesso ricorre a qualcosa di diverso come negli esempi [9] e [10].
//[9]
x++;
//[10]
++x;
//[11]
x = 10;
y = 2 * (x++);
//[12]
Un programma è una serie di istruzioni 10
x = 10;
y = 2 * (++x);
//[13]
x = 10;
x++;
y = 2 * x;
Parentesi
Se sei riuscito a passare la scuola media saranno per te cosa vecchia, ma le
parentesi possono essere usate per determinare l'ordine nel quale le operazioni
vengono eseguite. Normalmente * e / hanno la precedenza su + e -. Così 2*3+4 è
uguale a 10. Usando le parentesi, puoi forzare l'addizione ad essere eseguita per
prima: 2 * (3 + 4) uguale 14.
Divisione
L'operatore di divisione va trattato con particolare attenzione, perché è
leggermente differente quando viene usato con interi o a virgola mobile. Dai
un'occhiata ai seguenti esempi [14, 15].
//[14]
int x = 5, y = 12, ratio;
ratio = y / x;
Diventare un Xcoder
11 Capitolo 01
//[15]
float x = 5, y = 12, ratio;
ratio = y / x;
Nel primo caso [14], il risultato è 2. Solo nel secondo caso [15], il risultato è
quello che probabilmente ti aspetti: 2.4.
Booleani
Un Booleano è un semplice valore logico vero o falso, dove 1 e 0 stanno per true e
false, spesso usati in maniera intercambiabile e possono essere considerati
equivalenti:
True False
1 0
Sono spesso utilizzati per valutare se svolgere alcune azioni a seconda dal valore
booleano di qualche variabile o funzione.
Modulo
Un operatore con il quale probabilmente non avete familiarità è % (modulo).
Esso non funziona come si potrebbe pensare ovvero il calcolo di una percentuale.
//[16]
int x = 13, y = 5, remainder;
remainder = x % y;
21 % 7 è uguale a 0
22 % 7 è uguale a 1
23 % 7 è uguale a 2
Un programma è una serie di istruzioni 12
24 % 7 è uguale a 3
27 % 7 è uguale a 6
30 % 2 è uguale a 0
31 % 2 è uguale a 1
32 % 2 è uguale a 0
33 % 2 è uguale a 1
34 % 2 è uguale a 0
50 % 9 è uguale a 5
60 % 29 è uguale a 2
L’operatore % può tornarti utile, ma ricorda che lavora solo con interi. Un uso
molto comune è quello di determinare se un intero è dispari o pari.
Se è pari, il modulo di due è uguale a zero. Altrimenti sarà uguale ad un altro
valore. [17]
//[17]
int unIntero;
//Qui ci sarebbe il codice che imposta il valore di unIntero
if ((unIntero % 2) == 0)
{
NSLog(@"unIntero è pari");
}
else
{
NSLog(@"unIntero è dispari");
}
Diventare un Xcoder
13 Capitolo 01
Introduzione
Utilizzando nomi di variabili autoesplicativi possiamo rendere il nostro codice
molto più leggibile [1].
//[1]
float immagineLarg, immagineAltez, immagineArea;
immagineLarg = 8.0;
immagineAltez = 4.5;
immagineArea = immagineLarg * immagineAltez;
Fare un commento
Per creare un commento inizia la riga con due slash.
// Questo è un commento
/* Questo è un commento
che si estende su due righe*/
Un programma è una serie di istruzioni 14
OutComment
A breve ci occuperemo del debug di un programma e degli ottimi strumenti
forniti da Xcode al riguardo.
Uno dei modi di farlo alla "vecchia maniera", invece, si chiama Outcomment.
Racchiudendo una porzione di codice tra /* */ puoi disabilitare quel codice, per
vedere se il resto funziona come ci si aspetta. Questo ti permette di rintracciare
un bug.
Se, per esempio, la parte commentata contiene l'assegnazione di una particolare
variabile, puoi commentare l'assegnazione e inserire una riga temporanea per
assegnare un valore utile per testare il resto del tuo codice.
Perché commentare?
L'importanza dei commenti non sarà mai abbastanza ribadita.
Spesso è utile aggiungere una spiegazione in lingua umana (italiano, inglese...) di
ciò che accade all'interno di una serie di righe di codice. Questo permette di non
dover dedurre cosa il codice faccia e di capire se il problema può essere generato
da quella porzione di codice.
Dovresti anche usare i commenti per spiegare cose che non si possono dedurre
direttamente dal codice. Per esempio, se codifichi una funzione matematica,
usando un modello specifico descritto in dettaglio in qualche libro, dovresti
apporre un riferimento bibliografico al codice.
A volte è utile scrivere qualche commento prima di lavorare sul codice. Ti aiuterà
a strutturare meglio i pensieri e programmare diventerà più semplice.
Il codice nel presente libro non sempre è commentato come dovrebbe, solo
perché è già circondato da esaurienti spiegazioni.
Diventare un Xcoder
15 Capitolo 01
03: Funzioni
Introduzione
Il più lungo blocco di codice che abbiamo visto finora aveva solo cinque
istruzioni. Programmi costituiti da diverse migliaia di linee potrebbero sembrare
un traguardo lontano ma, a causa della natura di Objective-C, dobbiamo
discutere del modo in cui i programmi sono organizzati in questa fase iniziale.
Se un programma fosse costituito da una lunga, continua successione
d'istruzioni, sarebbe difficile trovare e correggere i bugs. Inoltre, una particolare
serie d'istruzioni potrebbe comparire in diversi punti del tuo programma. Se in
quella sequenza ci fosse un bug, dovresti correggere il medesimo bug in diversi
punti. Un incubo, perché è facile lasciarsene sfuggire uno o più.
Quindi è stato studiato un modo per organizzare il codice, rendendo più
semplice correggere i bugs.
La soluzione a questo problema è di raggruppare le istruzioni in base alla loro
funzione. Per esempio, potresti avere una sequenza d'istruzioni che permettono
di calcolare l'area della superficie di un cerchio. Verificato che questa serie
d'istruzioni è affidabile, non avrai mai più bisogno di controllare ancora quel
codice per vedere se il bug si trova li. La sequenza d'istruzioni, chiamata
funzione, ha un nome e puoi invocare quella sequenza d'istruzioni tramite quel
nome perché il suo codice venga eseguito.
Il concetto dell'uso delle funzioni è così fondamentale, che c'è sempre almeno
una funzione in ogni programma: la funzione main().
La funzione main() è ciò che il compilatore cerca, così saprà dove dovrà
cominciare l'esecuzione del codice a programma avviato.
La funzione main()
Diamo uno sguardo alla funzione main() più dettagliatamente. [1]
//[1]
main()
{ //[1.2]
// Body of the main() function. Put your code here.
} //[1.4]
L'istruzione [1.1] mostra il nome della funzione, ovvero "main", seguita dalle
parentesi aperta e chiusa. Mentre "main" è una parola riservata e la funzione
Un programma è una serie di istruzioni 16
//[2]
main()
{
// Variables are declared below
float pictureWidth, pictureHeight, pictureSurfaceArea;
// We initialize the variables (we give the variables a value)
pictureWidth = 8.0;
pictureHeight = 4.5;
// Here the actual calculation is performed
pictureSurfaceArea = pictureWidth * pictureHeight;
}
//[3]
main()
{
float pictureWidth, pictureHeight, pictureSurfaceArea;
pictureWidth = 8.0;
pictureHeight = 4.5;
pictureSurfaceArea = pictureWidth * pictureHeight;
}
circleArea() // [3.9]
{
Diventare un Xcoder
17 Capitolo 01
//[4]
main()
{
float pictureWidth, pictureHeight, pictureSurfaceArea,
circleRadius, circleSurfaceArea; // [4.4]
pictureWidth = 8.0;
pictureHeight = 4.5;
circleRadius = 5.0; // [4.7]
pictureSurfaceArea = pictureWidth * pictureHeight;
// Here we call our function!
circleSurfaceArea = circleArea(circleRadius); // [4.11]
}
//[5]
circleArea(float theRadius) // [5.1]
{
float theArea; // [5.3]
theArea = 3.1416 * theRadius * theRadius; // pi times r square [5.4]
return theArea; // [5.5]
Un programma è una serie di istruzioni 18
Nella [5.1] abbiamo definito che per la funzione circleArea() un valore di tipo
float è richiesto come input. Quando viene ricevuto, questo valore è
immagazzinato nella variabile nominata theRadius. Usiamo una seconda
variabile, theArea, per immagazzinare il risultato del calcolo [5.4], pertanto la
dobbiamo dichiarare [5.3], allo stesso modo in cui abbiamo dichiarato le
variabili nella funzione main() [4.4].
Avrai notato che la dichiarazione della variabile theRadius è stata collocata fra le
parentesi [5.1].
La linea [5.5] restituisce il risultato alla parte del programma da cui la funzione è
stata invocata. Come conseguenza, nella linea [4.11], la variabile
circleSurfaceArea è inizializzata con quel valore.
La funzione nell'esempio [5] è completa, eccetto per una cosa. Non abbiamo
specificato il tipo di dati che la funzione restituirà. Il compilatore richiede che lo
facciamo, per cui non abbiamo altra scelta che obbedire e indicare che è di tipo
float [6.1].
//[6]
float circleArea(float theRadius) //[6.1]
{
float theArea;
theArea = 3.1416 * theRadius * theRadius;
return theArea;
}
Come indica la prima parola della linea [6.1], il dato restituito da questa
funzione (in altre parole, il valore della variabile theArea) è di tipo float. Come
programmatore, dovrai assicurarti che la variabile circleSurfaceArea nella
funzione main() [4.4] sia anch'essa dello stesso tipo, in modo che il compilatore
non abbia alcuna ragione di assillarci.
Non tutte le funzioni richiedono un argomento. Se non ce n'è alcuno, le
parentesi () sono comunque obbligatorie, anche se sono vuote.
//[7]
int throwDice()
{
int noOfEyes;
// Code to generate a random value from 1 to 6
return noOfEyes;
Diventare un Xcoder
19 Capitolo 01
Restituire valori
Non tutte le funzioni restituiscono un valore. Se una funzione non restituisce
nessun valore, essa è di tipo void. L'istruzione return è quindi facoltativa. Se la
usi, la parola chiave return non dev'essere seguita da alcun valore o nome di
variabile.[8]
//[8]
void beepXTimes(int x);
{
// Code to beep x times
return;
}
//[9]
float pictureSurfaceArea(float theWidth, float theHeight)
{
// Code to calculate surface area
}
//[10]
int main() // [10.1]
{
float pictureWidth, pictureHeight, pictureSurfaceArea,
circleRadius, circleSurfaceArea;
pictureWidth = 8;
pictureHeight = 4.5;
circleRadius = 5.0;
pictureSurfaceArea = pictureWidth * pictureHeight;
Un programma è una serie di istruzioni 20
//[11]
float circleArea(float theRadius); // function declaration
Diventare un Xcoder
21 Capitolo 01
come mostrato sotto [12] e questa funzione potrebbe essere invocata nella nostra
funzione main(). È utile anche se il codice che abbiamo messo in una funzione
viene usato una sola volta. La funzione main() diventa più facile da leggere. Se
devi fare il debug del tuo codice, sarà più facile scoprire dove potrebbe trovarsi il
bug nel tuo programma. Potresti scoprire che si trova proprio in una funzione.
Invece di dover leggere una lunga sequenza d'istruzioni, devi solo verificare le
istruzioni della funzione, che sono facili da trovare, grazie alle parentesi graffe di
apertura e di chiusura.
//[12]
float rectangleArea(float length, float width) // [12.1]
{
return (length * width); // [12.3]
}
Come puoi vedere, in un caso semplice come questo, è possibile scrivere una singola
istruzione [12.3] che comprenda il calcolo e la restituzione del risultato. Ho usato la
variabile superflua theArea nella [10.14] solo per farti vedere come dichiarare una
variabile in una funzione.
Sebbene le funzioni che abbiamo definito noi stessi in questo capitolo sono
piuttosto banali, è importante capire che potresti modificare una funzione senza
alcun impatto sul codice che la invoca, fintanto che non cambierai la
dichiarazione della funzione (in altre parole, la sua prima linea).
Per esempio potresti cambiare i nomi delle variabili in una funzione e la
funzione funzionerebbe ancora (ciò non sconvolgerebbe il resto del programma).
Qualcun altro potrebbe scrivere la funzione e tu potresti usarla senza sapere cosa
succede dentro alla funzione. Tutto ciò che hai bisogno di sapere è come usare la
funzione. Che significa sapere:
• rectangleArea
• Due argomenti, entrambi float, dove il primo rappresenta la lunghezza e il
secondo la larghezza.
Un programma è una serie di istruzioni 22
Variabili protette
Il codice dentro alla funzione è protetto dal resto del programma e dalle altre
funzioni.
Questo significa che il valore di una variabile dentro ad una funzione non può
essere modificato da alcun'altra variabile di qualsiasi altra funzione, anche se ha
lo stesso nome. Questa è una delle principali caratteristiche di Objective-C. Nel
Capitolo 5, parleremo ancora di questo comportamento. Ma adesso, stiamo per
avviare Xcode ed eseguire il programma qui sopra [10].
Diventare un Xcoder
23 Capitolo 01
Introduzione
Abbiamo fatto buoni progressi con il nostro programma, ma non abbiamo
ancora discusso come mostrare a schermo i risultati della nostra elaborazione. Il
linguaggio Objective-C non offre costrutti per farlo ma fortunatamente altri
programmatori hanno scritto delle funzioni che ci vengono in aiuto e che
possiamo richiamare all'occorrenza. Ci sono vari metodi per mostrare a schermo
i risultati. In questo libro utilizzeremo una funzione fornita dall'ambiente
Cocoa: NSLog(). Così facendo non ci dobbiamo preoccupare di dover scrivere
una funzione personalizzata per mostrare a schermo i nostri risultati.
Usare NSLog()
Andiamo a vedere come viene usata NSLog():
//[1]
int main()
{
NSLog(@”Julia è la mia attrice preferita.”);
return 0;
}
Nota: nei successivi esempi verranno mostrate solo le parti interessanti della funzione
main().
Un programma è una serie di istruzioni 24
//[2]
NSLog(@””); [2.1]
NSLog(@” ”); [2.2]
L'istruzione [2.1] contiene zero caratteri e rappresenta una stringa vuota (ovvero
ha lunghezza zero). L'istruzione [2.2] invece non è una stringa vuota (anche se lo
sembra): essa contiene un singolo spazio, perciò ha lunghezza pari ad uno.
Diverse sequenze di caratteri speciali hanno un significato particolare in una
stringa. Questi caratteri speciali sono conosciuti come sequenze di escape.
Per esempio, per forzare l'ultima parola della nostra frase ad andare a capo
dev'essere inserito un codice speciale nell'istruzione [3.1]. Il codice da usare è \n.
//[3]
NSLog(@”Julia è la mia attrice \npreferita.”); [3.1]
Ora l'output del nostro programma sarà questo (è mostrata solo la parte
interessante):
Diventare un Xcoder
25 Capitolo 01
//[5]
int x, integerToDisplay;
x = 1;
integerToDisplay = 5 + x;
NSLog(@”Il valore dell'intero è %d.”, integerToDisplay);
Nota che tra parentesi abbiamo una stringa, una virgola ed il nome di una
variabile. Se notate, la stringa contiene qualcosa di strano: %d.
Come la backslash, anche il carattere % ha un significato particolare. Durante
l'esecuzione, al posto di %d sarà inserito il valore dopo la virgola, nel nostro caso
il valore della variabile integerToDisplay. L'output dell'esempio [5] sarà:
Il valore dell'intero è 6.
//[6]
float x, floatToDisplay;
x = 12345.09876;
floatToDisplay = x/3.1416;
NSLog(@”Il valore float è %f.”, floatToDisplay);
//[7]
float x, floatToDisplay;
x = 12345.09876;
floatToDisplay = x/3.1416;
NSLog(@”Il valore float è %.2f.”, floatToDisplay);
colonne contenenti dati tutti con la stessa (fissa) larghezza. Puoi specificare
questa larghezza con un valore intero tra % ed f (o % e d, a seconda dei casi). In
ogni modo se il valore da mostrare è più largo della larghezza impostata,
quest'ultimo valore sarà ignorato.
//[8]
int x = 123456;
NSLog(@”%2d”, x); [8.2]
NSLog(@”%4d”, x); [8.3]
NSLog(@”%6d”, x);
NSLog(@”%8d”, x); [8.5]
123456
123456
123456
123456
Nelle prime due istruzioni [8.2, 8.3] abbiamo richiesto uno spazio troppo
piccolo per il numero completo ma ad ogni modo lo spazio necessario viene
preso lo stesso. Solo l'istruzione [8.5] specifica una larghezza più grande del
valore, quindi ora vediamo che sono apparsi degli spazi vuoti addizionali.
È anche possibile combinare il numero di cifre significative dopo la virgola e la
larghezza del valore:
//[9]
float x=1234.5678
NSLog(@”Riserva 10 caratteri e mostra 2 cifre significative.”);
NSLog(@”%10.2f”, x);
//[10]
int x = 8;
float pi = 3.1416;
NSLog(@”Il valore intero è %d, il valore float è %f.”, x, pi); [10.3]
Diventare un Xcoder
27 Capitolo 01
//[10b]
int x = 8;
float pi = 3.1416;
NSLog(@”Il valore intero è %f, mentre il valore float è %f.”, x, pi);
da il seguente output:
Il valore intero è 0.000000, mentre il valore float è 0.000000.
#import <Foundation/Foundation.h>;
//[11]
#import <Foundation/Foundation.h> //[11.1]
float circleArea(float theRadius);
float rectangleArea(float width, float height);
int main()
Un programma è una serie di istruzioni 28
{
float pictureWidth, pictureHeight, pictureSurfaceArea,
circleRadius, circleSurfaceArea;
pictureWidth = 8.0;
pictureHeight = 4.5;
circleRadius = 5.0;
pictureSurfaceArea = rectangleArea(pictureWidth, pictureHeight);
circleSurfaceArea = circleArea(circleRadius);
NSLog(@”Area del cerchio: %10.2f.”, circleSurfaceArea);
NSLog(@”Area del rettangolo: %f. “, pictureSurfaceArea);
return 0;
}
Diventare un Xcoder
Compilare ed eseguire un programma 30
Introduzione
Il codice che abbiamo scritto fino ad ora non è altro che del testo che noi umani
riusciamo a leggere. Pur non essendo intuitivo per noi, lo è ancora meno per il
tuo Mac. Con esso non può farci nulla!
Serve un programma speciale, detto compilatore, per tradurre il codice di
programmazione in un codice eseguibile dal Mac. Il compilatore è una parte
dell'ambiente di programmazione Xcode. Dovresti aver installato Xcode usando
il disco che ti è stato fornito con la tua copia di Mac OS X. In ogni caso verifica
di aver l'ultima versione disponibile, che può essere scaricata alla sezione
sviluppatori a http://developer.apple.com (richiesta registrazione gratuita).
Creare un progetto
Avvia Xcode, che puoi trovare nella sottodirectory Applicazioni della directory
Developer. Quando avvii il programma per la prima volta ti sarà presentata la
finestra di Welcome dalla quale potrai lanciare i progetti più recenti, per il
momento non la utilizziamo quindi scegli Cancel.
Ora seleziona "New>New Project" nel menu "File". Comparirà una finestra di
dialogo con una lista di tutti i possibili tipi di progetto.
Diventare un Xcoder
31 Capitolo 05
Il progetto che stiamo per creare potrà essere eseguito dal Terminale. Se vuoi essere in
grado di eseguirlo evitandovi un po' di problemi assicurati di dare al tuo programma
un nome di una sola parola. Inoltre è abitudine consolidata non iniziare con la
maiuscola i nomi dei programmi da far eseguire da terminale. Al contrario i
programmi dotati di GUI dovrebbero avere nomi che iniziano con lettera maiuscola.
Esplorando Xcode
Dopo aver confermato la creazione del progetto ti si presenterà una finestra con
molti elementi. La finestra è divisa in due sezioni.
Assicurati di aver selezionato la visualizzazione Groups & Files (vedi il cerchio
rosso nell’immagine).
Diventare un Xcoder
33 Capitolo 05
Nella sezione "Gruops & Files" apri il gruppo "prova" e naviga fino alla cartella
prova. Al suo interno troverai un file chiamato "main.m" [1].
Ricordi che ogni programma deve contenere una funzione chiamata main() ?
Ecco, questo è il file che contiene quella funzione. Più avanti in questo capitolo
andremo a modificarla per includere il codice del nostro programma. Se apri
"main.m" selezionandolo da Group & Files, avrai una bella sorpresa.
Xcode ha già creato la funzione main() per te.
Compilare ed eseguire un programma 34
• La dichiarazione import necessaria per funzioni come NSLog(), che inizia con
un cancelletto.
• La funzione main().
• Le parentesi graffe che contengono il corpo del programma.
• Un commento, che ti invita ad inserire il tuo codice in quel punto.
• Una dichiarazione NSLog() per stampare una stringa sullo schermo.
• La dichiarazione return 0;.
Diventare un Xcoder
35 Capitolo 05
Sai già che le funzioni sono un modo per organizzare un programma, che ogni
programma ha una funzione main() e come sono strutturate le funzioni. In ogni
modo, devo ammettere che non è il momento di spiegarti tutto ciò che vedi
nell'esempio [1].
Ti chiedo, quindi, d'ignorare quelle linee ([1.3, 1.5 e 1.9]). Ci sono altre cose del
linguaggio Objective-C con cui devi familiarizzare prima di poter scrivere
semplici programmi. La buona notizia è che hai già superato due grossi scogli e
che i prossimi tre sono abbastanza semplici, prima di rituffarci nuovamente in
qualcosa di complicato.
Se proprio non vuoi essere lasciato senza una spiegazione eccone una sommaria.
Gli argomenti della funzione main() sono necessari per eseguire il programma da
terminale. Il tuo programma usa memoria. Memoria che altri programmi vorrebbero
usare quando hai finito di far girare il programmino. Come programmatore è tuo
dovere riservarti la memoria di cui hai bisogno. Altrettanto importante è liberare la
memoria quando hai finito. Questo è ciò a cui serve la dichiarazione "pool".
Compilare ed eseguire
Eseguiamo ora il programma fornitoci da Apple [1] cliccando il pulsante
"Run" (vedi la freccia rossa) per compilare ed eseguire l'applicazione.
Compilare ed eseguire un programma 36
Il bottone "Run".
Il risultato sarà che il programma verrà tradotto (compilato) in un linguaggio
comprensibile dal Mac e quindi eseguito. Il risultato è stampato nella finestra
"All Output", insieme ad altre informazioni aggiuntive. L'ultima frase dice che il
programma è terminato, con un valore di ritorno pari a 0. Qui puoi vedere il
valore di ritorno della funzione main(), come discusso nel capitolo 3 [7.9].
Quindi il nostro programma è giunto fino all'ultima riga e non è uscito
prematuramente. Fin qui tutto OK!
Bugging
Torniamo ora all'esempio [1] e vediamo che succede se c'è un bug nel
programma. Per esempio, modificando la dichiarazione NSLog() e
dimenticandoci il punto e virgola finale.
[2]
#import <Foundation/Foundation.h>
Diventare un Xcoder
37 Capitolo 05
Se clicchi sul pallino a sinistra nella linea segnalata ti verrà proposta anche la
correzione automatica (se il compilatore è in grado di proporla).
Il parsing è una delle prime cose che un compilatore fa, ovvero percorrere tutto il
codice e controllare se può capire ogni singola linea. Il tuo dovere di
programmatore è quello di aiutarlo a capire il significato di ciascuna parte.
Quindi per le dichiarazioni di import [2.1], dovrai inserire un cancelletto (#).
Per indicare la fine di una linea [2.8] dovrai apporre un punto e virgola. Quando
il compilatore raggiungerà la riga [2.9] noterà che manca un punto e virgola alla
riga prima. La morale è che il compilatore cerca di darci dei feedback che abbiano
senso, anche se non saranno un'accurata descrizione di quale sia il problema,
nell'esatta posizione dell'errore.
Compilare ed eseguire un programma 38
[3]
#import <Foundation/Foundation.>
circleRadius = 5.0;
pictureSurfaceArea = pictureWidth * pictureHeight;
circleSurfaceArea = circleArea(circleRadius);
NSLog(@”Area of picture: %f. Area of circle: %10.2f.”,
pictureSurfaceArea, circleSurfaceArea);
[pool drain];
return 0;
}
Diventare un Xcoder
39 Capitolo 05
{
return width*height;
}
Debugging
Quando un programma si complica, diventa più difficile eliminare gli errori.
Verrà quindi il momento che vorrai sapere cosa succede all'interno del
programma mentre viene eseguito.
Xcode rende questo molto semplice. Clicca sul margine grigio prima della
dichiarazione di cui vuoi conoscere il valore delle variabili; Xcode inserirà un
punto d'interruzione (breakpoint), rappresentato dall'icona di una freccia blu.
Compilare ed eseguire un programma 40
Nota che vedrai il valore di quelle variabili, prima che quella riga di codice venga
eseguita, quindi spesso avrai bisogno d'inserire il punto d'interruzione sulla riga
di codice immediatamente successiva a quella in cui sei interessato.
Ora clicca sul tasto "Run” ed apparirà la seguente finestra.
Diventare un Xcoder
41 Capitolo 05
Conclusione
Abbiamo visto tutto quello che serve per scrivere, correggere ed eseguire semplici
programmi per Mac OS X.
Se non sei intenzionato a creare programmi con interfacce grafiche, l'unica cosa
che devi fare adesso è di approfondire la tua conoscenza di Objective-C, per
Compilare ed eseguire un programma 42
Diventare un Xcoder
43 Capitolo 05
if()
A volte vorrai che il tuo codice faccia una serie di azioni solo se una particolare
condizione è soddisfatta. A questo scopo, ci vengono messe a disposizione delle
“parole chiave” speciali [1].
//[1]
// age è una variabile di tipo int che memorizza l’età dell’utente
if (age > 30) // Il simbolo > (maggiore) significa “più grande di” //[1.2]
{
NSLog(@”Hai più di 30 anni.”); //[1.4]
}
NSLog(@”Fine.”); //[1.6]
if() else()
Possiamo anche fornire un insieme alternativo d'istruzioni nel caso la condizione
non sia soddisfatta, usando l’espressione if...else [2].
//[2]
// age è una variabile di tipo int che memorizza l’età dell’utente
if (age > 30) //[2.2]
{
NSLog(@”Hai più di 30 anni.”); //[2.4]
}
else
{
NSLog(@”Hai meno di 30 anni.”); //[2.7]
}
NSLog(@”Fine.”);
Confronti
Oltre al segno di maggiore (>) [1.2][2.2], sono a tua disposizione i seguenti
operatori di confronto per i numeri:
== uguale a
> maggiore di
< minore di
>= maggiore o uguale a
<= minore o uguale a
!= non uguale a
Esercizio
Diamo un'occhiata più da vicino all'eseguire dei confronti. Un'operazione di
confronto ha solo due possibili risultati: vero oppure falso.
Diventare un Xcoder
45 Capitolo 05
//[4]
if ( (age >= 18) && (age < 65) )
{
NSLog(@”Hai da lavorare ancora una vita”);
}
//[5]
if (age >= 18)
{
if (age < 65)
{
NSLog(@” Hai da lavorare ancora una vita”);
}
}
Ripetizione di espressioni (for a while) 46
Introduzione
In tutto il codice che abbiamo discusso finora, ogni espressione veniva eseguita
solo una volta. Possiamo sempre ripetere del codice nelle funzioni invocandolo
ripetutamente [1].
//[1]
NSLog(@”Julia è la mia attrice preferita.”);
NSLog(@”Julia è la mia attrice preferita.”);
NSLog(@”Julia è la mia attrice preferita.”);
for()
Se conosci quante volte dev'essere ripetuta un'espressione (o un gruppo di
espressioni), puoi specificarlo inserendo quel numero nell'espressione for
dell'esempio [2].
//[2]
int x;
for (x = 1 ; x <= 10 ; x++)
{
NSLog(@”Julia è la mia attrice preferita.”); //[2.4]
}
NSLog(@”Il valore di x è %d”, x); //[2.6]
soddisfatta. L'ultima espressione [2.6] è stata inclusa per provarti che x è 11, non
10, dopo che il loop è finito.
A volte, avrai bisogno di fare step più larghi che solo un semplice incremento
usando x++. Tutto quello che devi fare è sostituire con l'espressione che ti serve.
L'esempio seguente [3] converte i gradi Fahrenheit in gradi Celsius.
//[3]
float celsius, tempInFahrenheit;
for (tempInFahrenheit = 0 ; tempInFahrenheit <= 200 ; tempInFahrenheit =
tempInFahrenheit + 20)
{
celsius = (tempInFahrenheit - 32.0) * 5.0 / 9.0;
NSLog(@”%10.2f -> %10.2f”, tempInFahrenheit, celsius);
}
while()
Objective-C ha due altri modi per ripetere un set di espressioni:
while () { }
do {} while ()
La prima è in sostanza identica al loop for che abbiamo discusso sopra. Inizia
eseguendo la valutazione di una condizione. Se il risultato della valutazione è
falso, le espressioni nel loop non sono eseguite.
Ripetizione di espressioni (for a while) 48
//[4]
int counter = 1;
while (counter <= 10)
{
NSLog(@”Julia è la mia attrice preferita.\n”);
counter = counter + 1;
}
NSLog(@”Il valore di counter è %d”, counter);
In questo caso, il valore del contatore è 11, ne avrai bisogno più tardi nel tuo
programma!
Con l'istruzione do {} while () , le espressioni tra parentesi graffe sono eseguite
come minimo una volta.
//[5]
int counter = 1;
do
{
NSLog(@”Julia è la mia attrice preferita.\n”);
counter = counter + 1;
}
while (counter <= 10);
NSLog(@”Il valore di counter è %d”, counter);
Diventare un Xcoder
49 Capitolo 07
Introduzione
Abbiamo aumentato le nostre conoscenze di Objective-C, ed ora siamo pronti
per discutere su come creare un programma con una Graphical User Interface
(GUI). Devo confessarvi una cosa. L' Objective-C è un'estensione del linguaggio
di programmazione chiamato C. Tutto quello di cui abbiamo discusso
precedentemente è principalmente C. In cosa differisce Objective-C dal C? Nella
parte "objective"; Objective-C tratta di nozioni astratte conosciute come oggetti.
Fino ad ora abbiamo principalmente trattato coi numeri. Come già sai,
Objective-C nativamente supporta il concetto di numeri. Ciò ci permette di
creare e manipolare numeri in memoria usando operatori matematici e funzioni
matematiche. Questo è ottimo quando la tua applicazione tratta numeri (ad
esempio una calcolatrice). Ma se la tua applicazione tratta cose tipo canzoni,
playlist, artisti ecc...? O se la tua applicazione controlla il sistema del traffico
aereo trattando con aerei, voli, aeroporti, etc.? Non sarebbe carino essere capaci
di manipolare anche queste cose con Objective-C, facilmente come facciamo
con i numeri? Questo è dove gli oggetti entrano in gioco. Con Objective-C, puoi
definire il tipo di oggetto che ti interessa trattare e poi scrivere l’applicazione che
lo manipola.
Oggetti in azione
Come esempio, prendiamo in considerazione come una finestra viene gestita da
un programma scritto in Objective-C, quale è Safari. Prendiamo una finestra
aperta di Safari sul tuo Mac.
In alto a sinistra, ci sono tre bottoni, di cui quello rosso è il bottone di chiusura.
Cosa accade se chiudi la finestra cliccando il bottone rosso? Un messaggio viene
spedito alla finestra e, in risposta, la finestra esegue il codice per chiudersi.
Ripetizione di espressioni (for a while) 50
Un oggetto (ad esempio la finestra) può contenere altri oggetti ( ad esempio i bottoni)
Classi
Se ci pensi puoi avere quante finestre vuoi di Safari; allora i programmatori
Apple:
Diventare un Xcoder
51 Capitolo 07
Quando crei una nuova finestra, è la classe che crea la finestra per te. Questa
classe rappresenta il concetto di finestra, e ogni particolare della finestra è
un'istanza di questo concetto ( nella stessa maniera 76 è un'istanza del concetto
di numero).
Variabili istanziate
La finestra che hai creato è presente in un certo punto dello schermo del tuo
Mac. Se la minimizzi nel Dock, e la fai riapparire, essa si riporterà nella stessa
posizione sullo schermo che aveva in precedenza. Come riesce questo lavoro?
La classe definisce variabili adeguate per ricordarsi la posizione della finestra sullo
schermo. L'istanza della classe, ad esempio l'oggetto, contiene i valori di queste
variabili. Così, ogni oggetto finestra contiene i valori di certe variabili, e gli
oggetti finestra differenti conterranno differenti valori per queste variabili.
Metodi
La classe non solo ha creato l'oggetto finestra, ma dà anche l'accesso a una serie
di azioni che può eseguire.
Una di queste azioni è “chiudi”. Quando tu clicchi il bottone di "chiusura" di
una finestra, il bottone spedisce il messaggio chiudi a quella finestra oggetto. Le
azioni che possono essere eseguite da un oggetto sono chiamati metodi, e come
puoi ben vedere assomigliano molto alle funzioni, quindi non dovresti avere
problemi ad imparare ad usarli, sempre se ci hai seguito.
Oggetti in memoria
Quando la classe crea un oggetto finestra per te, riserva della memoria (RAM)
per immagazzinare la posizione della finestra e tante altre informazioni, ma non
fa una copia del codice per chiudere la finestra. Questo potrebbe sembrare un
errore ma non è così. Il codice è lo stesso per ogni finestra e non ha bisogno di
essere presente tante volta, ma una sola; questo perché ogni oggetto finestra ha
accesso a questo codice nel momento in cui crei una nuova classe finestra. Il
codice che vedrai in questo capitolo contiene alcune istruzioni per riservare dello
spazio in memoria e rilasciarlo poi al sistema. Si tratta di un argomento avanzato
che per il momento non tratteremo.
ù
Ripetizione di espressioni (for a while) 52
Esercizio
La nostra applicazione
Il nostro obiettivo è di creare un'applicazione con due bottoni ed un campo di
testo. Alla pressione di uno dei bottoni, il campo di testo verrà riempito con un
valore diverso a seconda del bottone premuto. Pensa a una calcolatrice con due
bottoni che però non può fare calcoli. Sicuramente, una volta che avrai imparato
abbastanza potrai provare a creare una calcolatrice vera, ma procediamo a piccoli
passi.
Diventare un Xcoder
53 Capitolo 07
Quando la nostra istanza riceve un messaggio mandato da uno dei due bottoni
viene eseguito il metodo appropriato. Il codice del metodo è memorizzato nella
classe (non nell'istanza stessa). Durante l’esecuzione, questo metodo imposterà il
testo nell'oggetto campo testo.
Come fa il metodo nella nostra classe a sapere come impostare il testo nel campo
testo? Non lo sa; ma il campo testo sa cosa fare con il suo contenuto. Così noi
spediamo un messaggio al campo testo, chiedendogli di farlo. Quale tipo di
messaggio dovrebbe essere? Sicuramente, abbiamo bisogno di specificare il nome
del contenitore (nell’esempio l'oggetto campo testo nella nostra finestra). Poi
avremo bisogno di dire, nel messaggio, cosa vogliamo che il contenitore faccia.
Per farlo useremo il nome del metodo che il campo testo deve eseguire al
ricevimento del messaggio. Infine abbiamo bisogno di comunicare all'oggetto
campo testo quale valore mostrare (relativamente al bottone cliccato). Quindi il
messaggio spedito esprime non solo il nome dell'oggetto e del metodo, ma anche
un argomento (valore) da usare nel metodo dell'oggetto campo testo.
Uno schizzo dei messaggi scambiati tra gli oggetti della nostra applicazione
Ripetizione di espressioni (for a while) 54
//[1]
[oggetto_ricevente messaggio]; //[1.1]
[oggetto_ricevente messaggio:argomento_del_messaggio]; //[1.2]
Creiamo il progetto
Vediamo adesso come, nella pratica, si può fare tutto quello che abbiamo appena
spiegato. Avvia Xcode per creare un nuovo progetto e selezionia Cocoa
Application
Diventare un Xcoder
55 Capitolo 07
Product Name e lascia le altre opzioni come sono e salva. Creato il progetto,
seleziona MainMenu.xib, che si trova sotto Groups & Files, nella cartellina con il
nome del progetto (Esercizio1).
Ripetizione di espressioni (for a while) 56
Creiamo la GUI
Diventare un Xcoder
57 Capitolo 07
Ora cerca l’oggetto chiamato “Label” e allo stesso modo dei pulsanti trascina
anche lui nella finestra.
Ti consiglio di esplorare la Library, dopo che abbiamo finito questo progetto, per
prendere familiarità su come aggiungere altri oggetti alla finestra.
Ripetizione di espressioni (for a while) 58
Classe background
Come dicevamo prima, ora dobbiamo creare una classe. Ma prima di farlo
andiamo un po' più a fondo su come lavorano le classi. Per salvarti da inutili
sforzi di programmazione, sarebbe bello se potessi costruire la tua classe su una
base già esistente, invece che partire da zero. Se tu per esempio, vuoi creare una
finestra con speciali proprietà (capabilities), hai bisogno di aggiungere solamente
il codice di queste proprietà, non di riscrivere codice per tutto, tipo come
minimizzare o chiudere una finestra. Costruendo su quello che altri
programmatori hanno fatto, puoi inserire tutti questi nuovi comportamenti
Diventare un Xcoder
59 Capitolo 07
Se il metodo non può essere trovato, hai spedito un messaggio che non può essere
gestito. È come richiedere ad un'officina di cambiare le gomme del tuo slittino. Anche
il capo dell'officina non potrà mai aiutarti. In questo caso Objective-C segnalerà un
errore.
Custom classes
E se volessimo implementare delle caratteristiche particolari per un metodo
ereditato dalla superclasse? In questo caso dobbiamo sovrascrivere il metodo della
superclasse. Per esempio, puoi scrivere del codice che, cliccando il tasto di
chiusura, muove la finestra fuori dalla tua vista prima che si chiuda. La tua classe
speciale per la finestra potrebbe usare lo stesso metodo nominato per chiudere
una finestra come lo definisce Apple. Così quando la tua speciale finestra riceve
un messaggio di chiusura, il metodo eseguito è il tuo, e non quello Apple.
Quindi, ora la finestra si muoverà fuori lato, prima di chiudersi realmente.
In realtà il metodo per chiudere una finestra, è già stato scritto da Apple.
All'interno del nostro metodo di chiusura, noi possiamo anche invocare il
metodo di chiusura implementandolo dalla nostra superclasse, sebbene ciò
richieda una leggera differenza nella chiamata, per essere sicuri che il nostro
metodo di chiusura non sia ricorsivo. [2]
//[2]
// Codice per muovere la finestra fuori dalla vista.
[super close]; // Usa il metodo close della superclasse.
Ripetizione di espressioni (for a while) 60
Diventare un Xcoder
61 Capitolo 07
Quando crei un nuova classe dovresti dargli un nome che renda bene l’idea di
che classe si tratta. Per l'istanza, abbiamo già visto che in Cocoa la classe usata
per rappresentare le finestre è NSWindows, Un altro esempio è la classe che
viene usata per rappresentare i colori, che è nominata NSColor. Nel nostro caso,
la classe MAFoo che stiamo creando è giusto per illustrare come gli oggetti
comunicano tra loro in un'applicazione.
Ecco perché abbiamo dato un nome generico e non uno specifico.
Bene abbiamo appena creato un’istanza della nostra classe MAFoo in Interface
Builder. Questo ci permetterà di far dialogare codice ed interfaccia grafica.
Diventare un Xcoder
63 Capitolo 07
Creiamo le connessioni
Il nostro prossimo passo è creare le connessioni tra i bottoni (da cui sono spediti
i messaggi) e il nostro oggetto MAFoo. In aggiunta, creeremo anche una
connessione tra l'oggetto MAFoo e il campo testo, questo perché un messaggio
sarà spedito all'oggetto campo testo. Un oggetto non ha modo di spedire un
messaggio ad un altro oggetto se non ha un riferimento a quest'ultimo. Facendo
una connessione tra un bottone e il nostro oggetto MAFoo, noi facciamo si che
il bottone abbia un riferimento al nostro oggetto MAFoo. Usando questo
riferimento, il bottone riuscirà a spedire messaggi all'oggetto MAFoo.
Analogamente, stabilendo una connessione tra l’oggetto e il campo testo
renderemo possibile inviare messaggi a quest'ultimo.
Consideriamo cosa deve fare l'applicazione. Ognuno dei bottoni può spedire,
quando cliccato, un messaggio corrispondente ad una particolare azione.
Questo messaggio contiene il nome del metodo della classe MAFoo che
dev'essere eseguito. Il messaggio viene spedito all'istanza della classe MAFoo che
abbiamo appena creato, l'oggetto MAFoo. (Ricorda: l'oggetto istanziato non
contiene il codice per realizzare l'azione, ma la classe sì). Quindi, questo
messaggio spedito all'oggetto MAFoo fa eseguire un metodo della classe MAFoo
per fare qualcosa: in questo caso, spedisce il messaggio al l’oggetto campo testo.
Come ogni messaggio, questo consiste nel nome di un metodo (che l’oggetto
campo testo dovrà eseguire). In questo caso , il metodo dell'oggetto campo testo
ha l'obiettivo di mostrare un valore, e questo valore dev'essere spedito come
parte di un messaggio (chiamato "argomento", ricordate?), assieme al nome del
metodo per mostrarlo sul campo testo.
La nostra classe ha bisogno quindi di due azioni (metodi), i quali saranno
mandati in esecuzione dai due oggetti bottoni. La nostra classe ha bisogno anche
di un outlet, una variabile per ricordare a quale oggetto (nell’esempio l'oggetto
campo testo) sarà spedito il messaggio.
Seleziona il file MAFoo.h. Dopo la parola @private scrivi
in questo modo hai dichiarato la variabile textField che sarà usata come
riferimento al campo testo, IBOutlet scritto all’inizio fa si che essa sia visibile
anche nella gestione dell’interfaccia grafica.
Dopo la ‘}’ e prima di @end scrivi
-(IBAction)setTo5:(id)sender;
-(IBAction)reset:(id)sender;
Ripetizione di espressioni (for a while) 64
in questo modo hai dichiarato i due metodi che saranno associati ai due bottoni.
Nel nostro esempio useremo il metodo setTo5 per mostrare 5 nel campo testo ed
il metodo reset per mostrare 0.
//[3]
/* MAFoo */
#import <cocoa/cocoa.h> // [3.2]
Diventare un Xcoder
65 Capitolo 07
Prima di stabilire le connessioni tra gli oggetti diamo dei nomi significativi ai
nostri due bottoni. Poichè il primo chiederà all’istaza MAFoo di visualizzare il
numero 5 nel campo testo, lo chiamiamo “Set to 5” (per cambiare nome al
bottone: doppio click sul suo nome nell’oggetto e inserisci il nuovo nome). Allo
stesso modo chiamiamo il secondo “Reset”. Nota che questo passaggio di dare
un nome particolare ad un bottone non è necessario per far funzionare
correttamente la nostra applicazione. E‘ solo che vogliamo che l’interfaccia
utente sia il più descrittiva possibile per l’utente finale.
Per creare le connessioni per le Actions fai click con il destro sul bottone Set to 5
e trascina il mouse sull’oggetto Object; lascia il pulsante del mouse e seleziona
setTo5: nel popUp che ti sarà presentato.
Ripetizione di espressioni (for a while) 66
Diventare un Xcoder
67 Capitolo 07
Ma che cosa è successo? Presto detto; creando le connessioni tra gli oggetti e
l’istanza della tua classe MAFoo hai generato una parte codice che permetterà di
far funzionare la tua applicazione, il tutto senza scrivere una sola riga.
Nella realtà il codice generato sarà a te del tutto, o comunque in parte invisibile,
ma fidati che c’è e tra un pò te ne darò la dimostrazione.
@implementation MAFoo
- (id)init
{
self = [super init];
if (self) {
// Initialization code here.
}
return self;
}
- (void)dealloc
{
[super dealloc];
}
@end
Prima di tutto viene importato il file di intestazione MAFoo.h [4.2]. Poi trovi
due metodi (funzioni) predefiniti
- (id)init
- (void)dealloc
//[5]
#import "MAFoo.h"
@implementation MAFoo
- (id)init
{
self = [super init];
if (self) {
// Initialization code here.
}
return self;
}
- (IBAction)reset:(id)sender
{
[textField setIntValue:0]; // [5.6]
}
- (IBAction)setTo5:(id)sender
{
[textField setIntValue:5]; // [5.11]
}
- (void)dealloc
{
[super dealloc];
}
@end
Pronti a ballare?
Giunto a questo punto sei pronto per testare la tua prima applicazione. Premi
quindi “Run” e attendi un istante che Xcode crei l’applicazione e la visualizzi.
Adesso puoi divertirti a premere i bottoni e vedere il risultato.
Diventare un Xcoder
69 Capitolo 07
Introduzione
Nel capitolo precedente abbiamo imparato cosa sono i metodi. Abbiamo scritto
(il corpo di) due metodi, ma ne abbiamo anche utilizzato uno fornito da Apple ,
setIntValue:, metodo usato per visualizzare un intero in un oggetto textfield. Come
possiamo fare a scoprire tutto sui metodi a nostra disposizione?
Ricorda, per ogni metodo creato da Apple che usi non devi scrivere nessun codice.
Inoltre, è più probabile che sia senza errori. Quindi, vale sempre la pena spendere un
pochino di tempo per verificare se sono presenti dei metodi adeguati per il tuo
programma.
Esercizio
Seleziona il file MainMenu.xib (accedendo così alla componente Interface
Builder di XCode), se scegli un oggetto dalla Library e ci lasci sopra il puntatore
per un secondo si apre una piccola finestra descrittiva con in più un nome. Se
metti il cursore sull'icona bottone, vedrai "NSButton". Se lo tieni sopra il campo
di testo , vedrai "NSTextField". Ognuno di questi nomi è il nome di una classe.
Diamo un'occhiata alla classe "NSTextField" per vedere quali metodi sono
disponibili.
Diventare un Xcoder
71 Capitolo 09
La prima cosa che devi notare è che questa classe eredita da una serie di altre
classi. L'ultimo della lista è il padre di tutto, l'NSObject. Un po' sotto vi è la
sezione Tasks nella quale sono elencati i metodi raggruppati per tipologia di
compiti e che sono poi descritti nella sezione successiva Instance Methods.
NSControl
Eredita da NSView : NSResponder : NSObject
Come puoi vedere siamo saliti di una classe. Nella lista dei metodi si nota un
gruppo:
Troviamo i metodi 72
- setIntValue:
-(void)setIntValue:(int)anInt
oggetto MAFoo non riceverà nessun valore indietro dall'oggetto campo di testo.
Questo va bene. Dopo i due punti, (int) indica che la variabile anInt deve essere
un intero. Nel nostro esempio noi mandiamo un valore di 5 o 0, che sono interi
e questo va bene. A volte è un po' difficile trovare qual è il metodo da usare. Lo
vedrai meglio quando prenderai più dimestichezza con la documentazione,
quindi continua ad allenarti.
Che cosa succede se vuoi leggere il valore del nostro campo di testo dell'oggetto
textField? Ricordi il fatto che le funzioni racchiudono tutte le variabili al loro
interno? Lo stesso vale per i metodi. Spesso, tuttavia, gli oggetti hanno una
coppia di metodi, chiamati "Accessors", uno per la lettura e uno per
l'impostazione del valore. Conosciamo già l'ultimo, quello è il metodo
setIntValue:. Il primo sarà invece:
//[1]
-(int) intValue
//[2]
int resultReceived = [textField intValue];
Di nuovo, nelle funzioni (e metodi), tutti i nomi delle variabili sono schermati.
Questo è fantastico per i nomi delle variabili, perché non devi temere che
l'impostazione di una variabile in una parte del tuo programma interesserà una
variabile con lo stesso nome nella tua funzione. Tuttavia i nomi delle funzioni
devono essere unici nel programma. Objective-C va un passo oltre nella
schermatura: i nomi dei metodi devono essere univoci all'interno di una sola
classe, ma diverse classi possono avere metodi con lo stesso nome. Questa è una
caratteristica ottima per i grandi programmi, in quanto i programmatori
possono scrivere classi indipendenti l'una dall'altra, senza dover temere conflitti
nel nome dei metodi.
C'è di più. Il fatto che differenti metodi in classi differenti possano avere lo
stesso nome è chiamato in gergo polimorfismo, ed è una delle cose che rendono
la programmazione orientata agli oggetti così speciale. Esso consente di scrivere
porzioni di codice senza dover conoscere in anticipo quali sono le classi di
oggetti che stai manipolando. E' necessario solo che, durante l'esecuzione ,
l'oggetto attuale capisca il messaggio inviato.
Troviamo i metodi 74
Diventare un Xcoder
75 Capitolo 09
10: awakeFromNib
Introduzione
Apple ha fatto un sacco di lavoro per te, rendendo più facile la creazione dei tuoi
programmi. In una tua piccola applicazione, non devi preoccuparti di disegnare
una finestra e un bottone su uno schermo, e molte altre cose.
La maggior parte del lavoro è resa disponibile attraverso due frameworks. Il
Foundation Kit framework che abbiamo importato nell'esempio [12] del
capitolo 4, che fornisce la maggior parte dei servizi non associati alle interfacce
grafiche. L'altro framework, chiamato Application Kit, si occupa di mostrare gli
oggetti sullo schermo e di gestire i meccanismi di interazione con l'utente.
Entrambi i framework sono ben documentati.
Esercizio
Tutte le informazioni per la finestra sono memorizzate in un file xib (nelle
versioni precedenti si chiamava nib che sta per NeXT Interface Builder, non
approfondiamo in questa sede la differenza tra i due tipi di file). Questa è un
buon indice del fatto che il metodo di cui abbiamo bisogno possa essere parte di
Application Kit. Vediamo come ottenere informazioni su questo framework.
In Xcode, vai nel menu Help e seleziona Documentation & API Reference.
Nella finestra della documentazione scrivi Application Kit nel campo di ricerca e
premi Return.
Xcode ti fornisce risultati multipli. Nel gruppo System Guides vi è un
documento denominato Application Kit Framework Reference se non è
nell’elenco visualizzato clicca su show more results. All'interno troverete un elenco
dei servizi forniti dal framework. Sotto la voce Protocols c'è un link chiamato
NSNibAwaking. e se fai fa clic su di esso, otterrai la documentazione per la classe
NSNibAwaking.
Troviamo i metodi 76
Ok, adesso abbiamo trovato il nostro metodo, tutto quello che dobbiamo fare è
di aggiungerlo all'implementazione nel file MAFoo.m [1.15].
Diventare un Xcoder
77 Capitolo 09
visualizzerà zero.
Puntatori 78
11: Puntatori
Attenzione!
Questo capitolo contiene concetti avanzati e si occupa di concetti fondamentali
del C che potrebbero intimidire i principianti. Se non capisci tutto adesso, non
ti preoccupare. Grazie al cielo, in generale, anche se capire come funzionano i
puntatori è utile, non è essenziale per iniziare a programmare in Objective-C
Introduzione
Quando dichiari una variabile il tuo Mac associa a questa variabile dello spazio
in memoria dove immagazzinare il valore. Per esempio, esaminiamo la seguente
istruzione:
//[1]
int x = 4;
Quando viene eseguita, il tuo Mac trova dello spazio nella sua memoria, che non
sia ancora usato, e annota che questo spazio è dove la variabile x scrive il suo
valore (certamente avremmo potuto e dovuto usare un nome più descrittivo per
la nostra variabile). Guarda nuovamente l'istruzione [1]. Indicando il tipo della
variabile (qui int) fai sapere al tuo computer quanto spazio in memoria è
necessario per contenere il valore di x. Se il valore fosse stato long long o double,
ci sarebbe voluta più memoria.
Diventare un Xcoder
79 Capitolo 11
Referenziare variabili
Data una variabile, tu puoi prendere il suo indirizzo scrivendo & prima della
variabile. Per esempio, per prendere l'indirizzo di x tu scriverai &x.
Usare i puntatori
Dichiara un puntatore in questo modo:
//[2]
int *y;
//[3]
y = &x;
*y
*y = 5
x = 5
Puntatori 80
I puntatori sono utili perché spesso non vuoi riferirti al valore di una variabile,
ma all'indirizzo di essa. Per esempio, tu potresti voler programmare una funzione
che aggiunge 1 a una variabile. Bene, non puoi farlo in questo modo?
//[4]
void increment(int x)
{
x = x + 1;
}
//[5]
int myValue = 6;
increment(myValue);
NSLog(@”%d:\n”, myValue);
Questo codice mostra 6 sul monitor. Perché? Non incrementa myValue chiamando
la funzione di incremento? No, al momento no. Come vedi, la funzione in [4]
prende il valore di myValue (nell'esempio il numero 6), lo incrementa di 1 e...
fondamentalmente, lo butta. Le funzioni lavorano solo con i valori che gli passi,
non sulle variabili che li contengono. Anche se modifichi x (come puoi vedere in
[4]), tu modifichi solo il valore che la funzione riceve. Ogni modifica verrà persa
quando la funzione sarà completata. Inoltre, x, non è necessariamente una
variabile: se si chiama incremento(5); che cosa ti aspetti di incrementare? Se vuoi
scrivere una versione di una funzione di incremento che funzioni, per esempio
che accetti una variabile come suo argomento e ne incrementi permanentemente
il valore, hai bisogno di passare l'indirizzo di una variabile. In questo modo, tu
modifichi cosa è memorizzato nella variabile, non solo il valore corrente. Quindi
usi un puntatore come argomento:
//[6]
void increment(int *y)
{
*y = *y + 1;
}
Diventare un Xcoder
81 Capitolo 11
12: Stringhe
Introduzione
Sinora abbiamo visto diverse tipologie base di dati, quali int, long, float, double,
BOOL. Inoltre nello scorso capitolo abbiamo avuto modo di introdurre i
puntatori. Quando abbiamo accennato alle stringhe, lo abbiamo fatto solo in
relazione alla funzione NSLog(). Questa funzione, come abbiamo avuto modo di
vedere, ci permette di stampare una stringa a video e di inserire il valore di una
variabile in corrispondenza delle parole chiave inizianti con l'operatore %, ad
esempio %d.
//[1]
float piValue = 3.1416;
NSLog(@"Qui ci sono alcuni esempi di stringhe stampate a video.\n");
NSLog(@"Pi approssimativamente %10.4f.\n", piValue);
NSLog(@"Il numero di facce di un dado é %d.\n", 6);
Non abbiamo trattato prima le stringhe come tipi di dati per una buona ragione:
diversamente da interi e numeri a virgola mobile le stringhe sono veri oggetti,
create usando la classe NSString o la classe NSMutableString. Studiamo queste
classi, partendo da NSString.
NSString
Ancora puntatori
//[2]
NSString *favoriteComputer; //[2.1]
favoriteComputer = @"Mac!";
NSLog(favoriteComputer);
//[3]
int *y;
Diventare un Xcoder
83 Capitolo 12
Il simbolo @
Bene, perché ci ritroviamo ovunque questo simbolo @? Il fatto é che Objective-
C é un estensione del linguaggio C, che ha i suoi modi per trattare con le
stringhe. Per differenziare le nuove tipologie di stringhe, che ricordiamo essere
oggetti a tutti gli effetti, Objective-C usa la notazione @.
Esercizio
Naturalmente é possibile dichiarare e inizializzare una stringa in un unico
momento [4].
//[4]
NSString *favoriteActress = @"Julia";
Il puntatore favoriteActress punta alla memoria dove risiede l'oggetto che rappresenta
la stringa "Julia".
Dopo aver inizializzato la variabile, es. favoriteComputer, puoi dare alla variabile
un altro valore, ma non puoi cambiare la stringa stessa [5.7], perché é un'istanza
della classe NSString. Dettagli al riguardo a breve.
Stringhe 84
//[5]
#import <Foundation/Foundation.h>
int main (int argc, const char *argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSString *favoriteComputer;
favoriteComputer = @”iBook”; // [5.7]
favoriteComputer = @”MacBook Pro Intel”;
NSLog(favoriteComputer);
[pool release];
return 0;
}
NSMutableString
Una stringa della classe NSString é detta immutabile, perché non può essere
modificata.
A che serve una stringa che non può essere modificata? Stringhe di questo genere
sono più facili da gestire per il sistema operativo, quindi il programma può essere
più veloce. Ti accorgerai, scrivendo programmi in Objective-C, che spesso non
avrai bisogno di modificare le tue stringhe.
Di tanto in tanto, certo, potresti necessitare di stringhe che debbano essere
modificate. Per questo motivo esiste una classe diversa la quale crea oggetti
stringa modificabili. La classe é NSMutableString e ne parleremo più avanti in
questo capitolo.
Esercizio
Prima di tutto assicuriamoci che tu abbia capito che le stringhe sono oggetti.
Visto che sono oggetti possiamo mandare loro dei messaggi. Per esempio
possiamo mandare il messaggio length [6].
//[6]
#import <Foundation/Foundation.h>
Diventare un Xcoder
85 Capitolo 12
I programmatori spesso usano nomi quali foo e bar per le variabili quando spiegano
le cose. In realtà non sono dei buoni nomi, perché non sono descrittivi, esattamente
come x. In questo caso li usiamo in modo che non ti troverai spiazzato incontrandoli
in una discussione in internet.
Alla riga [6.10] mandiamo all'oggetto foo, il messaggio length. Il metodo length
é definito nella classe NSString nel seguente modo:
- (unsigned int)length
Puoi anche modificare i caratteri della stringa in maiuscoli [7]. A questo scopo
manda alla stringa il messaggio appropriato, uppercaseString, che dovresti essere
in grado di rintracciare da solo nella documentazione (controlla i metodi
disponibili per la classe NSString).
Alla ricezione di questo messaggio l'oggetto stringa crea e restituisce un nuovo
oggetto stringa uguale a se stesso, ma con ciascun carattere convertito nel suo
corrispettivo maiuscolo.
//[7]
#import <Foundation/Foundation.h>
//[8]
#import <Foundation/Foundation.h>
Alla linea [8.8], il metodo mutableCopy (che é fornito dalla classe NSString)
crea e restituisce una stringa modificabile con lo stesso contenuto del ricevente.
Quindi, dopo l'esecuzione della linea [8.8], foo punta ad un oggetto stringa
mutabile che contiene la stringa "Julia!".
Diventare un Xcoder
87 Capitolo 12
Ancora puntatori!
Precedentemente in questo stesso capitolo abbiamo affermato che, in Objective-
C, gli oggetti non sono mai manipolati direttamente, ma sempre attraverso
puntatori. Questo é il motivo, per esempio, per cui usiamo la notazione
puntatore alla linea [8.7]. In realtà, quando usiamo la parola "oggetto" in
Objective-C, quello che intendiamo in realtà é "il puntatore all'oggetto". Ma
siccome usiamo sempre gli oggetti attraverso i puntatori, usiamo la parola
"oggetto" per brevità. Che gli oggetti siano sempre utilizzati attraverso i
puntatori ha un'importante ripercussione che devi assolutamente capire: molte
variabili possono riferirsi allo stesso oggetto contemporaneamente. Per esempio,
dopo l'esecuzione della linea [8.7], la variabile foo si riferisce ad un oggetto
rappresentante la stringa "Julia!", qualcosa che possiamo rappresentare nel
seguente modo:
foo Julia!
Gli oggetti sono sempre manipolati attraverso i puntatori
Adesso supponiamo di assegnare il valore di foo alla variabile bar in questo modo
bar = foo;
Il risultato di questa operazione é che sia foo che bar adesso puntano allo stesso
oggetto:
Stringhe 88
foo Julia!
bar
Più variabili possono riferirsi allo stesso oggetto
[9]
#import <Foundation/Foundation.h>
Diventare un Xcoder
89 Capitolo 12
13: Arrays
Introduzione
A volte avrai la necessità di gestire insiemi di dati. Per esempio, potresti avere
bisogno di gestire un elenco di stringhe. Sarebbe piuttosto scomodo usare una
variabile per ognuna di quelle stringhe. Esiste in questo caso una soluzione
migliore: l'array.
Un array è una lista ordinata di oggetti (o, più precisamente, una lista di
puntatori di oggetti). Puoi aggiungere un oggetto all'array, rimuoverlo o chiedere
all'array di farti sapere quale oggetto è memorizzato ad un dato indice (cioè ad
una data posizione) inoltre puoi chiedere all'array quanti oggetti contiene in quel
momento.
0 First string
1 Second string
2 Third string
Esempio: Un array contenente tre stringhe
Più avanti in questo capitolo ti daremo degli esempi di codice dove potrai vedere
gli effetti della numerazione con partenza da zero.
Questi arrays sono specifici dei linguaggio Objective-C e Cocoa. Esiste un' altro tipo
di array nel linguaggio C (che è anche parte del Objective-C), ma non vogliamo
trattarlo in questa sede. Questo è giusto per ricordare, tuttavia, che potresti leggere
Diventare un Xcoder
91 Capitolo 13
qualcosa a riguardo degli array nel linguaggio C, e tranquillizzarti che non hanno
niente a che fare con NSArrays o NSMutableArrays.
[NSMutableArray array];
Noterai che questo oggetto è autorilasciato in automatico quando viene creato; cioè e
allegato al NSAutoreleasePool e impostato per essere cancellato dal metodo della classe
che lo ha creato. Chiamare la class method equivale a:
Nel caso in cui vogliamo che l'array sopravviva di più rispetto al tempo di
autorelease, dovrai trasmettere all' instance un messaggio di -retain.
Nella documentazione Cocoa, i metodi che inviamo alle classes sono identificati
da un simbolo "+", invece del simbolo "-" che vediamo solitamente prima del
nome dei method (Capitolo 8 [4.5]). Per esempio, nella documentazione
vediamo questa descrizione per il metodo array:
array
+ (id)array
Esercizio:
Torniamo al codice. Il seguente programma crea un array vuoto, memorizza tre
stringhe al suo interno, e poi stampa il numero di elementi di cui è composto
l'array.
//[1]
#import <foundation/foundation.h>
//[2]
#import <foundation/foundation.h>
Diventare un Xcoder
93 Capitolo 13
Spesso dovrai percorrere l'array per poter lavorare con ogni elemento. Per fare
questo è possibile usare strutture a ciclo come nel programma seguente che
stampa ogni elemento dell'array ed il suo indice:
//[3]
#import <foundation/foundation.h>
Nota che gli array non sono limitati all'uso delle stringhe, infatti possono
contenere qualsiasi oggetto tu desideri.
//[4]
[myArray replaceObjectAtIndex:1 withObject:@"Hello"];
Conclusioni
Come puoi vedere, i method names in objective-C sono simili a frasi con un
buco al loro interno (preceduti da un "due punti"). Quando tu invochi un
metodo tu completi il buco con il valore corrente creando cosi una "sentence" di
senso compiuto. Questo modo di indicare i nomi dei metodi e le loro
invocazioni proviene dallo Smalltalk ed è uno dei maggiori punti di forza del
linguaggio Objective-C in quanto rende il codice piu espressivo. Quando tu crei
un tuo metodo personale dovresti sforzarti ad assegnargli un nome
comprensibile. Questo renderà il codice objective-C più leggibile e questa è una
cosa molto importante nel semplificare la manutenzione del tuo programma.
Diventare un Xcoder
95 Capitolo 14
Introduzione
Se ricordi, nei capitoli precedenti ho evitato di spiegare alcuni statement negli
esempi. Questi statement parlavano di memoria. Il tuo programma non è il solo
programma sul tuo Mac, e la RAM è una merce preziosa. Quindi se il tuo
programma non ha bisogno più di una parte di memoria, questa andrebbe
restituita nuovamente al sistema. Quando la mamma ti ha detto che dovevi
essere educato e vivere in armonia con la comunità, ti stava insegnando come
programmare! Anche se il tuo programma è l'unico in esecuzione, la memoria
non liberata potrebbe eventualmente relegare il tuo programma in un angolo e il
computer potrebbe rallentare.
Garbage Collection
Le tecniche di gestione di memoria usate da Cocoa e introdotte successivamente
in questo capitolo sono comunemente conosciute come "Reference Counting".
Puoi trovare una spiegazione completa di questo sistema di gestione della
memoria di Cocoa in alcuni libri avanzati o articoli (vedi Capitolo 15).
Mac OS X 10.5 Leopard introduce una nuova forma di gestione della memoria
per Objective-C 2.0, conosciuta come Cocoa Garbage Collection. Garbage
collection gestisce la memoria automaticamente, eliminando il bisogno di
esplicitare il rilascio o l'autorelease di oggetti Cocoa. La magia del garbage
collection funziona su tutti gli oggetti Cocoa che ereditano da NSObject o
NSProxy e permette ai programmatori di scrivere semplicemente meno codice
rispetto alle versioni precedenti di Objective-C. Non c'è molto altro da dire su di
esso, in pratica. Dimenticate tutto ciò che avete imparato in questo capitolo!
Per esempio, durante l'esecuzione del programma, il tuo oggetto può essere
referenziato da molti altri oggetti, e quindi non deve essere distrutto perché c'è
una possibilità che possa essere usato da altri oggetti (cercare di utilizzare un
Diventare un Xcoder
97 Capitolo 14
oggetto che sia stato distrutto può causare un crash nel tuo programma o un
comportamento imprevedibile).
Il contatore retain
Per aiutarti a distruggere gli oggetti quando non sono più necessari, Cocoa
associa un contatore a ogni oggetto, che rappresenta quello che è chiamato il
"retain count" di un oggetto. Nel tuo programma, quando memorizzi un
riferimento a un oggetto, devi farlo sapere all'oggetto incrementando il retain
count di uno. Quando rimuovete un riferimento ad un oggetto, il retain deve
essere decrementato di uno. Quando il retain count di un oggetto diventa uguale
a zero, l'oggetto sa che non è più referenziato da nessuno e può distruggersi
tranquillamente. L'oggetto che si distrugge libera la memoria associata.
Per esempio, supponiamo che la tua applicazione sia un jukebox digitale e tu hai
oggetti rappresentanti canzoni e playlist. Supponi che la data canzone oggetto sia
referenziata da tre playlist oggetto. Se non è referenziata altrove la tua canzone
oggetto avrà un retain count di tre.
Playlist 1 A song
retain
count = 3
Playlist 1
Playlist 3
Retain e Release
Per aumentare il retain count di un oggetto, non devi far altro che inviare
all'oggetto un messaggio di retain.
[anObject retain];
Per diminuire il retain count di un oggetto, non devi far altro che inviare
all'oggetto un messaggio di release.
[anObject release];
Autorelease
Cocoa offre anche un meccanismo chiamato "autorelease pool" che ti consente
di inviare un messaggio di rilascio ritardato ad un oggetto, non
immediatamente, ma in un secondo tempo. Per usarlo, devi registrare l'oggetto
con quello che viene chiamato autorelease pool, inviando un messaggio di
autorelease.
[anObject autorelease];
Diventare un Xcoder
99 Capitolo 14
15: Appendice A
Il modesto obiettivo di questo libro era quello di insegnare le basi di Objective-C
nell'ambiente Xcode. Se sei passato attraverso il libro due volte e hai provato gli
esempi con le tue variazioni, sei pronto per imparare come scrivere la "killer
application" che stai cercando di creare. Questo libro ti ha dato una conoscenza
sufficiente per risolvere i tuoi problemi in tempi breve. Come hai fatto in questo
capitolo, sei pronto per utilizzare altre risorse, e quelle che ti menzioniamo qui
sotto dovrebbero avere la tua attenzione. Un importante consiglio prima di
iniziare a scrivere il tuo codice: non partire subito, controlla i framework, perché
Apple potrebbe già avere fatto il lavoro per te, o fornirti le classi che con poco
lavoro ti porteranno a quello che ti serve. Inoltre, qualcun altro potrebbe aver già
fatto tutto quello che ti serve, e reso disponibile il codice sorgente. Quindi
spendi un pochino del tuo tempo guardando attraverso la documentazione e
cercando su internet. La tua prima visita deve essere al sito degli sviluppatori
Apple:
http://developer.apple.com
http://osx.hyperjeff.net/reference/CocoaArticles.php
http://www.cocoadev.com
http://www.cocoadevcentral.com
http://www.cocoabuilder.com
http://www.stepwise.com
I siti sopra hanno un numero molto grande di link ad altri siti o altre fonti di
informazioni. Puoi anche iscriverti alla cocoa-dev mailing list a
http://lists.apple.com/mailman/listinfo/cocoa-dev. Questo è il posto dove puoi
scrivere le tue domande. Gli altri membri faranno del loro meglio per aiutarti. In
cambio, sii educato e prima verifica se sia possibile trovare la risposta alla tua
domanda negli archivi (http://www.cocoabuilder.com). Per alcuni consigli su
come postare domande sulla mailing list guarda "How To Ask Questions e
Smart Way" al http://www.catb.org/~esr/faqs/smart-questions.html
Ci sono diversi ottimi libri sullo sviluppo su Cocoa. Programming in Objective-
C, di Stephen Kochan é rivolto ai principianti.
Gestione della memoria 100
Altri libri assumono che tu abbia almeno una qualche conoscenza acquisita da
questo libro. Noi personalmente abbiamo trovato utili Cocoa Programming for
Mac OS X di Aaron Hillegass of the Big Nerd Ranch, il quale ha insegnato
Xcode per una vita. Vi segnaliamo inoltre Cocoa with Objective-C di James
Duncan Davidson e Apple, pubblicato da O'Reilly.
Speriamo che questo libro ti sia piaciuto e che abbia, in un qualche modo,
alimentato ancora di più il tuo interesse verso quella che è la programmazione
per Mac OSX.
Diventare un Xcoder