Page 1

Guida pratica a!’iPhone SDK"

1


INDICE Prefazione"

6

Capitolo 1: Introduzione al SDK e ad XCode"

7

Introduzione"

7

Panoramica sul SDK"

7

XCode"

8

Capitolo 2: Come creare un nuovo progetto"

11

I template di XCode"

11

Creare un nuovo progetto"

13

Interface Builder"

13

Capitolo 3: Il nostro primo progetto, He!oWorld!"

16

Creiamo la struttura grafica"

16

Definiamo gli elementi e le azioni"

17

Scriviamo il codice necessario"

20

Facciamo nascondere la tastiera"

21

Capitolo 4: TrashApp, gestiamo le immagini"

23

Definiamo l’applicazione"

23

Definiamo l’aspetto grafico."

24

Implementiamo il movimento del logo"

27

Il ripristino del logo"

29

Capitolo 5: UIToolbar e auto-rotazione" Definiamo l’applicazione" Guida pratica a!’iPhone SDK"

31 31 2


Definiamo l’aspetto grafico"

31

Scriviamo il codice necessario"

34

Capitolo: 6: NSTimer e UIProgressView"

37

Definiamo l’applicazione"

37

Definiamo l’aspetto grafico"

37

Scriviamo il codice"

39

Capitolo 7: AccessContact, accediamo a!a rubrica"

43

Definiamo il progetto"

43

Definiamo la struttura grafica"

44

Scriviamo il codice necessario"

45

Capitolo 8: Creiamo un mini browser con le UIWebView"

48

Creiamo la struttura grafica"

48

Definiamo i componenti e co!eghiamo le azioni"

49

Scriviamo il codice per aprire la pagina desiderata"

51

Capitolo 9: UITableView, gestiamo le tabe!e"

53

Parte 1: creiamo e definiamo la tabe!a"

53

Creiamo un nuovo progetto"

53

Inseriamo il codice necessario"

54

Parte 2: Inseriamo alcune funzionalità"

57

Permettiamo la cance!azione di una riga"

57

Rendiamo le ce!e selezionabili"

58

Parte 3: Implementiamo la ricerca"

60

Guida pratica a!’iPhone SDK"

3


A$iungiamo il box di ricerca"

60

Modifichiamo i metodi già esistenti"

61

Implementiamo la ricerca"

64

Capitolo 10: gestiamo più viste (file “.xib” multipli)"

67

Definiamo la struttura del progetto"

67

Definiamo la prima vista"

68

Definiamo la seconda vista"

69

Scriviamo il codice necessario"

71

Capitolo 11: Come creare una TabBar Application"

74

Parte 1: la struttura di base"

74

Creiamo una TabBar “pulita”"

74

Definiamo le due viste"

75

Creiamo l’aspetto grafico de!e due viste"

76

Impostiamo la TabBar"

79

Parte 2: Inseriamo una NavigationBar"

82

Creiamo un nuovo elemento per la TabBar"

82

Definiamo l’aspetto del nuovo elemento"

84

Implementiamo due viste di dettaglio"

87

Definiamo l’aspetto de!e due viste di dettaglio"

88

Come richiamare le due viste via codice"

91

Capitolo 12: XML"

94

Cosa è XML?"

94

XML nel SDK di iPhone"

96

Guida pratica a!’iPhone SDK"

4


Creiamo la struttura grafica"

96

Scriviamo il codice necessario"

98

Capitolo 13: SQL"

103

Definiamo un nuovo progetto"

103

Definiamo la classe “Data”"

105

Creiamo il database"

109

Concludiamo l’applicazione"

113

Guida pratica a!’iPhone SDK"

5


Prefazione Questo libro racchiude tutti i tutorial che ho creato sulla programmazione per iPhone e iPod Touch. Non vuole essere un manuale esauriente o sostituirsi alla documentazione ufficiale Apple, ma solo uno strumento per chi è alle prime armi, oppure per chi vuole imparare qualcosa che ancora non sa. Troverete una serie di guide pratiche, da seguire passo per passo, commentate e spiegate, per consentire a tutti di imparare e capire quello che viene fatto. Ringrazio chiunque legga queste pagine, sperando di potervi aiutare in un vostro scopo, sia lavorativo o per pura passione (come la mia). Ringrazio la mia fidanzata, che mi ha sempre sopportato e supportato, seppur non sappia niente di programmazione! Ringrazio Fabiano Confuorto, fondatore e amministratore di iSpazio, una stupenda community che mi ha fatto scoprire il mondo iPhone, e che mi ha dato l’opportunità di creare e pubblicare i miei primi tutorial. Ringrazio Steve Jobs, per aver creato Mac e l’iPhone, cercando sempre la perfezione nelle cose. E ricordatevi, solo essendo curiosi e affamati è possibile scoprire e creare qualcosa di nuovo e veramente innovativo. “Siate affamati, siate fo!i.”

Guida pratica a!’iPhone SDK"

6


Capitolo 1: Introduzione al SDK e ad XCode I NTRODUZIONE Con il rilascio del firmware 2.0, Apple ha segnato una svolta nel settore mobile: non era mai stato così semplice sviluppare e vendere le proprie applicazioni. Per permettere tutto ciò, Apple ha creato AppStore, uno spazio che si integra al già famoso e collaudato iTunes Store. Qualsiasi sviluppatore, indipendente o azienda già affermata, può pubblicare le proprie creazioni semplicemente acquistando una licenza annua, al prezzo di 99$ (79€ per noi europei). Quali sono i vanta$i legati a!’acquisto di una licenza? Sono molti, e valgono il prezzo da pagare. La cosa più importante è, come già detto, la possibilità di vendere le proprie applicazioni in AppStore. Ci sono, però, altri vantaggi: la possibilità di scaricare e installare le versioni beta dei nuovi firmware (per testare la compatibilità delle proprie applicazioni); la possibilità di installare i propri progetti anche sull’iPhone / iPod Touch direttamente da XCode (cosa che non è possibile senza licenza); l’accesso ad un forum specifico in cui saranno esperti Apple a dare risposte e ad aiutare gli sviluppatori in difficoltà; la disponibilità di una documentazione più ampia e più dettagliata. Come vedete non si tratta di sciocchezze. Ma come si sviluppano le applicazioni? Il tutto è davvero molto semplice (in pieno stile Apple): insieme al firmware 2.0, infatti, è stato rilasciato un SDK (Software Development Kit) ufficiale, che integra tutti gli strumenti necessari per creare applicazioni e giochi per iPhone e iPod To u c h . Q u e s t o S D K è l i b e r a m e n t e s c a r i c a b i l e d a l l ’ i P h o n e D e v C e n t e r (http://developer.apple.com/iphone/), previa registrazione gratuita (ma si può accedere alla sezione anche con il proprio account di iTunes). L’iPhone Dev Center è l’area di Apple dedicata agli sviluppatori (ovviamente di applicazioni per iPhone), in cui si può trovare davvero tantissimo materiale molto utile: esempi con codice ben commentato, documentazione delle librerie, documenti teorici, video, e molto altro ancora. Come ho già detto, per pubblicare applicazioni in AppStore è necessario disporre della licenza ufficiale. Questo, però, non basta per vedere pubblicate le proprie creazioni: ogni applicazione, infatti, passa sotto il controllo di Apple, che decide se accettarle o meno. Le applicazioni presenti in AppStore, infatti, devono rispettare il contratto del SDK, che prevede alcune limitazioni: è vietato, ad esempio, duplicare funzioni già presenti nel S.O. dell’iPhone (come l’invio di SMS e MMS), oppure sono vietate applicazioni con contenuto a sfondo sessuale o violento. Non pensate, quindi, di poter fregare Apple: c’è chi si è visto rifiutare la propria applicazione anche per una semplice icona.

P ANORAMICA SUL SDK Dopo aver scaricato e installato l’SDK (un’immagine dmg di circa 2 GByte), troverete tutto il necessario per sviluppare nella cartella “/Developer/Applications”. Gli strumenti (davvero molto potenti) che Apple mette a disposizione sono i seguenti:

Guida pratica a!’iPhone SDK"

7


• Dashcode, è un utile tool con cui potremo creare pagine web, widget (anche per la Dashboard di Mac OS X) e altro; • Instruments, permette di analizzare e valutare le prestazioni delle nostre applicazioni (in termini di consumo di memoria, impiego del processore, etc). È destinato, ovviamente, agli sviluppatori più esperti. • Interface Builder, grazie a questa applicazione sarà davvero un gioco da ragazzi creare l’aspetto grafico dei nostri programmi. Potremo inserire qualsiasi tipo di oggetto (bottoni, label, viste) semplicemente trascinando gli oggetti nella nostra schermata. • Quartz Composer, è un tool che permette di creare animazioni ed effetti grafici, da utilizzare poi in altri programmi. • XCode, è l’ambiente di sviluppo vero e proprio. Sarà qui, infatti, che andremo a creare i nostri progetti, scrivere il codice e compilare il tutto. È lo strumento, insieme ad Interface Builder, che utilizzeremo di più.

XC ODE Analizziamo, ora, come si presenta XCode. Aprendo un progetto (vedremo nel capitolo 2 come crearne un nuovo) otterremo la seguente schermata:

Guida pratica a!’iPhone SDK"

8


Potete notare tre sezioni principali: a sinistra troviamo “Groups & Files”, in cui abbiamo tutti i file che compongono il nostro progetto. Troveremo, quindi, le classi, le immagini inserite, i framework utilizzati. A destra, invece, possiamo vedere l’editor del codice, che ci assisterà e ci permetterà di scrivere il nostro codice. La barra in alto, infine, ci offre la possibilità di compilare ed installare la nostra applicazione, sul dispositivo che preferiamo: il nostro iPhone (solo nel caso in cui abbiamo la licenza ufficiale) oppure l’iPhone Simulator (un simulatore che ci permetterà di testare le nostre applicazioni comodamente sul Mac, senza dover installare nulla sul nostro iPhone). Particolare importanza ha il menù a tendina presente a sinistra della barra. Se lo apriamo troviamo le seguenti voci:

Nella prima parte, denominata “Active SDK” andremo a selezionare la versione del firmware con cui vogliamo che sia compatibile la nostra applicazione. Questo è necessario in quanto spesso, con il rilascio di nuovi firmware, vengono aggiunte anche nuove funzioni al SDK (le API). Quindi, un’applicazione scritta e compilata per il firmware 2.2 potrebbe non funzionare con una versione inferiore del firmware (spesso è proprio impossibile installarla, in quanto l’AppStore controlla questa compatibilità in fase di installazione). Al contrario, se compiliamo l’applicazione per la versione 2.1 funzionerà sicuramente (a meno che non utilizziate delle API con dei bug) sulla 2.2. È importante, quindi, scegliere con cura la versione da utilizzare, per non

Guida pratica a!’iPhone SDK"

9


escludere parte di utenza dall’utilizzo della nostra applicazione. È possibile, inoltre, scegliere se eseguirla sul simulatore (e in tal caso ci basta scegliere quelle con prefisso “Simulator”) oppure sul nostro iPhone. La seconda impostazione molto importante riguarda “Active Configuration”: selezionando l’opzione “Debug” otterremo un’applicazione più pesante, progettata per essere testata e corretta (proprio in quella che viene definita fase di debug); la versione ”Release”, invece, è molto più leggera ed è pronta per essere rilasciata e pubblicata in AppStore.

Guida pratica a!’iPhone SDK"

10


Capitolo 2: Come creare un nuovo progetto Abbiamo dato un’occhiata al SDK e ad XCode. È venuto il momento di iniziare a vedere gli strumenti che XCode ci mette a disposizione per realizzare i nostri progetti. In questo capitolo vedremo come creare un nuovo progetto, quali template XCode ci mette a disposizione e le caratteristiche principali di Interface Builder.

I TEMPLATE

DI

XC ODE

Avviando XCode e selezionando “File -> New Project...”, si aprirà la seguente finestra:

Potete notare che XCode ci fornisce vari template, ovvero delle strutture già pronte, che ci permetteranno di realizzare applicazioni sullo stile di quelle native. Non dovremo perdere tempo, quindi, per replicare lo stile delle altre applicazioni, perché è Apple stessa che ce li mette a disposizione.

Guida pratica a!’iPhone SDK"

11


(

Navigation-Based"

"

Tab Bar Application" "

"

Utility Application

Analizziamo, ora, i vari template che ci vengono forniti. • Navigation-Based Application, genera un’applicazione in cui possiamo navigare in sotto-livelli. Per farvi un esempio, pensate alla struttura di “Impostazioni” nel vostro iPhone: avete una barra in alto che visualizza il titolo della sezione corrente, e vi permette, tramite un bottone, di tornare alla sezione precedente. Questa barra viene chiamata “Navigation Bar”. Utile per creare applicazioni con tabelle, in cui vogliamo mostrare anche le informazioni sui vari elementi. • OpenGL ES Application, questa è sicuramente la tipologia più complessa, in quanto si basa sulla tecnologia OpenGL (http://it.wikipedia.org/wiki/OpenGL), sfruttata principalmente per realizzare videogiochi o animazioni grafiche complesse. In questo libro non analizzeremo questa tipologia di applicazioni. • Tab Bar Application, fornisce un’applicazione con la “tab bar”, ovvero la barra nera composta da più sezioni (ad esempio quella che trovate nell’applicazione nativa “Musica”). • Utility Application, questa tipologia implementa un menù che viene richiamato ruotando la schermata principale. Anche in questo caso, potete trovare una similitudine con l’applicazione “Meteo”: se premete sulla “i” presente a fondo pagina, la schermata ruoterà e vi permetterà di modificare i settaggi dell’applicazione. • View-Based Application, fornisce un’applicazione vuota, senza nessuna implementazione particolare. Questo template è composto da una finestra, chiamata “MainWindow”, e una vista, “[nome_progetto]ViewController”, che viene caricata proprio dalla finestra principale. Sarà questo punto di partenza per tutti i nostri tutorial. • Window-Based Application, è molto simile al caso precedente, ma il template fornito è composto solamente da una finestra (non è presente quindi la vista “[nome_progetto]ViewController”).

Guida pratica a!’iPhone SDK"

12


C REARE

UN NUOVO PROGET TO

In ogni tutorial che vedremo, sarà necessario creare un nuovo progetto. Per fare ciò, vi basterà aprire XCode, selezionare “File -> New Project...”, si aprirà la finestra con la scelta del template, che abbiamo appena analizzato. Scegliete il template desiderato (generalmente sarà ViewBased Application), cliccate su “Choose..” e nel box successivo inserite il nome del nostro progetto. Finito!

I NTERFACE B UILDER Scorrendo la sezione “Groups & Files” possiamo vedere tutti i file che XCode ha già inserito per noi. Nel capitolo 3 vedremo come creare la nostra prima applicazione (il classico HelloWorld), ora ci limitiamo ad analizzare le caratteristiche principali dell’Interface Builder. Facciamo doppio clic su “[nome_progetto]ViewController.xib”, nella cartella “Resources”, e si aprirà Interface Builder. Ci ritroveremo con una situazione simile a questa:

Potete notare vari strumenti sul vostro desktop: la libreria, la schermata della nostra applicazione (per ora completamente grigia), ed altri strumenti. Analizziamo ora questi componenti.

Guida pratica a!’iPhone SDK"

13


• Library, è la libreria da cui possiamo inserire tutti gli oggetti che desideriamo. Se non è già aperta, ci basterà andare in “Tools -> Library” e si aprirà una finestra come quella a lato. Scorrendo la barra laterale, potete notare moltissimi componenti, come bottoni, label di testo, viste, barre e molto altro. Tutti questi elementi potranno essere utilizzati nelle nostre applicazioni. Per inserirli basta trascinare un componente nella schermata dell’applicazione, e posizionarlo a proprio piacere (questo è vero per tutti i componenti tranne i “Controllers”, che potrete riconoscere perché hanno uno sfondo giallo).

• Vista o finestra, è la nostra vista, ovvero la finestra che verrà visualizzata sull’iPhone. Potremo personalizzarla a nostro piacimento, e impareremo nei capitoli successivi come fare. L’unica cosa che vi faccio notare, è la freccia presente a destra del nome della vista:

Se provate a cliccarla, noterete che la vista ruota: questo perché sarà possibile implementare la possibilità di ruotare la nostra applicazione quando l’utente ruota il proprio iPhone. Vedremo in dettaglio questo aspetto in un tutorial successivo. • Panne!o documenti, questo pannello vi mostra tutti i componenti del vostro file xib. All’inizio vi potrà sembrareinutile, però quando l’applicazione inizierà a diventare complessa, vi sarà molto utile per ritrovare tutti i componenti della vostra finestra.

Guida pratica a!’iPhone SDK"

14


• Inspector, è sicuramente la parte più importante di Interface Builder, in quanto ci permette di impostare qualsiasi proprietà, relativa ad ogni oggetto (dalla vista al singolo bottone). Potremo, quindi, modificare l’aspetto degli oggetti, collegare le azioni, modificarne la dimensioni. Insomma, potrete agire su moltissimi aspetti (il tutto senza scrivere una riga di codice). L’Inspector è composto da 5 parti: ✴Attributes, qui possiamo variare gli attributi generici dei nostri oggetti, ad esempio il colore, la dimensione del font, ed altre proprietà che impareremo poco alla volta. ✴Connections, è uno dei pannelli principali. Qui andremo a collegare le azioni agli oggetti. Cosa significa? Ve lo spiego con un esempio. Supponiamo di avere un bottone nella nostra vista, e vogliamo che quando viene premuto venga scritto “Ciao” in una casella di testo. Creeremo, quindi, un’azione, che si occuperà di scrivere “Ciao”. Dovremo, poi, collegare questa azione al bottone, in modo che quando l’utente preme il bottone, viene eseguito il comportamento desiderato. Vedrete che con i prossimi tutorial tutto questo sarà più familiare. ✴Size, questa sezione permette, come dice la parola stessa, di modificare le dimensioni dell’oggetto, e di modificarne anche la posizione e l’ancoraggio (ovvero dove deve essere fissato, questo sarà fondamentale quando implementeremo la rotazione della schermata). ✴Identity, in questo pannello potremo definire la classe, gli oggetti e le azioni che ci servono, senza scrivere una riga di codice! Potremo fare tutto in maniera davvero molto semplice, e ci basterà un clic per salvare la classe che avremo creato e le azioni relative. Abbiamo così completato la panoramica sull’Interface Builder. Mi pare inutile, per ora, dilungarmi in altri aspetti, che vi saranno sicuramente più chiari e familiari con un po’ di pratica. In pochissimo tempo, non riuscirete più a fare a meno di Interface Builder!

Guida pratica a!’iPhone SDK"

15


Capitolo 3: Il nostro primo progetto, HelloWorld! In questo capitolo realizzeremo la nostra prima applicazione, il classico HelloWorld! Chiederemo all’utente il proprio nome (ad esempio Tizio) e alla pressione di un bottone faremo apparire il messaggio “Ciao Tizio”. Niente di complicato quindi, però cercate di capire bene tutti i passaggi, in modo da non avere lacune su queste cose basilari.

C REIAMO

LA STRUT TURA GRAFICA

Iniziamo quindi creando un nuovo progetto di tipo “View-Based Application” e chiamiamolo “HelloWorld”. Apriamo quindi il file “HelloWorldViewController.xib”, che avvierà anche l’Interface Builder. Ora dobbiamo creare la struttura grafica, che deve essere simile a questa:

Come potete osservare, ci sono tre componenti principali: 1.una UITextField in cui l’utente potrà inserire il proprio nome; 2.una UIButton, con la scritta “Saluta!”, che l’utente dovrà premere per far apparire il saluto; 3.due UILabel, una con la scritta “Nome” (e questa serve solo per rendere più intuitivo il nostro programma), l’altra posta a centro schermo (che contiene la stringa Label). È importante impostare le dimensioni di questa ultima label in modo che occupi tutta la larghezza

Guida pratica a!’iPhone SDK"

16


della vista, altrimenti avremo problemi quando andremo a stampare il messaggio di saluto in seguito. Tramite “Attribute Inspector” possiamo definire alcune proprietà per questi oggetti. Selezioniamo ad esempio la UITextField, e impostiamo i seguenti valori: • “Capitalize”: “Words” (ovvero quando l’utente inizia a digitare il proprio nome la prima lettera viene scritta in maiuscolo); • “Corrections”: “No” (disabilitiamo la correzione automatica per questo campo); • Spuntiamo l’opzione “Clear Context Before Drawing” (cancellerà il contenuto già presente non appena l’utente seleziona il campo). A vostro piacere potete anche impostare altre proprietà, provatene alcune per prendere un po’ più di confidenza. Prima di proseguire, diamo un’occhiata a ciò che compone questo file (lo potete trovare nel pannello dei documenti):

Potete notare tre elementi, che XCode ha già definito per noi. • File’s Owner, come dice la parola stessa, è il proprietario del file. È, in sostanza, la classe che gestisce la nostra finestra, ovvero che gestisce ogni singolo aspetto. Nel nostro caso sarà la classe “HelloWorldViewController”, dove poi andremo a scrivere il codice necessario. • First Responder, per ora non è un componente che ci interessa, però sappiate che si occupa, ad esempio, della gestione del multi-touch. • View, è la nostra vista, ovvero la schermata che abbiamo definito. In questo caso ne abbiamo solo una, ma nulla ci vieta di definirne svariate e richiamarle poi a nostro piacimento.

D EFINIAMO

GLI ELEMENTI E LE AZIONI

Dobbiamo ora definire gli elementi e le azioni necessarie. Potremmo fare questa operazione da Interface Builder (e impareremo a farlo dal prossimo tutorial), ma per questa volta lo faremo

Guida pratica a!’iPhone SDK"

17


via codice, in modo che capiate bene come XCode lavora. Salviamo tutto e chiudiamo Interface Builder, tornando così in XCode. Nella cartella “Classes” noteremo quattro file: due con estensione “.h” e due con estensione “.m”. I file “.h” stanno ad indicare le classi di intestazione, ovvero dove vengono definiti i metodi e i componenti necessari, ma non vi è alcuna implementazione dei metodi. Saranno i file con estensione “.m” a contenere tutte le implementazioni dei metodi, ovvero il codice delle varie funzioni. Iniziamo, quindi, aprendo il file “He!oWorldContro!er.h”, in cui dovremo definire gli oggetti che ci serviranno. Nel nostro esempio, saranno due gli elementi da definire: la UITextField in cui l’utente inserisce il proprio nome (e da cui noi dobbiamo leggerne il valore), e la UILabel in cui scriveremo il saluto. Dovremo, poi, definire un’azione, quella che verrà richiamata alla pressione del bottone. Ecco il codice da inserire: 1 2 3 4 5 6 7 8 9 10 11 12 13 14

#import <UIKit/UIKit.h> @interface HelloWorldViewController : UIViewController { ! IBOutlet UITextField *fieldNome; ! IBOutlet UILabel *labelSaluto; } -(IBAction)saluta; @property (nonatomic, retain) IBOutlet UITextField *fieldNome; @property (nonatomic, retain) IBOutlet UILabel *labelSaluto; @end

Abbiamo dichiarato una UITextField e una UILabel, proprio i due componenti che ci servono. Possiamo notare che entrambe le dichiarazioni sono precedute dalla clausola “IBOutlet”, che indica ad Interface Builder che è possibile collegare questo metodo ad un elemento grafico. Questo è necessario perché, come vedrete fra poco, ci permetterà di collegare l’oggetto creato tramite Interface Builder con quello dichiarato in XCode. Dopo queste due dichiarazioni, trovate l’intestazione del metodo “saluta”, e anche in questo caso trovate una clausola ”IBAction”: anche questa sta a significare che l’azione è collegata ad un componente di Interface Builder. Le due property, poi, servono per poter utilizzare senza problemi le proprietà degli oggetti che abbiamo definito. Ora salviamo il file (Cmd + S) e riapriamo “HelloWorldViewController.xib”. Dobbiamo collegare questi componenti con quelli effettivamente inseriti nella nostra vista. Dal pannello dei documenti selezionate il componente “File’s Owner”. Aprendo il “Connections Inspector” dovreste vedere un pannello come questo:

Guida pratica a!’iPhone SDK"

18


Potete notare che sono presenti i componenti che abbiamo definito via codice! Ora non dobbiamo fare altro che collegarli agli elementi adeguati. Prendiamo il pallino a fianco di “fieldNome” e trasciniamolo fino alla UITextField della nostra vista. Avremo così collegato i due elementi! Ripetiamo la stessa operazione con “labelSaluto”, trascinando il pallino sulla UILabel posta a centro schermo. Stessa operazione va eseguita per l’azione “saluta”. Collegatela al bottone, ma quando rilasciate il bottone del mouse vi apparirà un menù come quello che trovate qui a fianco. Sono tutte le azioni che può gestire un bottone. Noi selezioniamo “Touch Up Inside”, ovvero un azione di click e rialscio (un singolo tap insomma). Volendo potremmo scegliere di avviare l’azione quando il bottone viene rilasciato, ma per il nostro scopo non cambia niente. Se avete eseguito tutto correttamente avrete un pannello “Connections Inspector” come questo:

Abbiamo così concluso la definizione dei componenti della nostra applicazione. Salviamo tutto e chiudiamo Interface Builder.

Guida pratica a!’iPhone SDK"

19


S CRIVIAMO

IL CODICE NECE SSARIO

Dobbiamo ora implementare il metodo “saluta”, che si occuperà di leggere il nome inserito dall’utente e stampare il messaggio di benvenuto sulla label predisposta. Apriamo il file “HelloWorldViewController.m” e inseriamo il seguente codice: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27

#import "HelloWorldViewController.h" @implementation HelloWorldViewController // importiamo i componenti di cui abbiamo definito le property @synthesize fieldNome, labelSaluto; // azione richiamata alla pressione del bottone -(IBAction)saluta{ ! // leggiamo la stringa contenuta nella UITextField (il nome dell'utente) ! NSString *nome = fieldNome.text; ! ! if ([nome length] == 0){ ! ! // l'utente non ha inserito nessun nome ! ! labelSaluto.text = [[NSString alloc] initWithFormat:@"Ciao anonimo!"]; ! }else{ ! ! // salutiamo l'utente ! ! labelSaluto.text = [[NSString alloc] initWithFormat:@"Ciao %@",nome]; ! } } - (void)dealloc { ! [labelSaluto dealloc]; ! [fieldNome dealloc]; ! [super dealloc]; }

Analizziamo il codice poco alla volta. L’istruzione presente alla riga 3 che ha il compito di caricare gli elementi di cui prima abbiamo definito le “property”. Potrebbe sembrare un po’ strana, ma per ora prendetela come regola. Dalla riga 9 alla 20 troviamo la definizione del metodo “saluta”. In tale metodo, non facciamo altro che leggere il nome inserito dall’utente (tramite “fieldNome.text”, che ci restituisce la stringa contenuta nella UITextField) e assegnarlo alla variabile “nome” (riga 11). Tramite una costrutto “if ” (dalla riga 13 alla 19) andiamo poi a controllare se tale stringa è vuota (e quindi l’utente ha premuto il tasto senza inserire nessun nome) oppure se vi è un valore. Ovviamente inseriamo due messaggi di saluto diversi a seconda del caso. Particolare attenzione merita parte dell’istruzione alla riga 18, ed in particolare questo pezzo di codice: “@"Ciao %@",nome”.

Guida pratica a!’iPhone SDK"

20


• “@”, la prima chiocciola sta ad indicare che ciò che segue è una stringa. La sintassi è sempre la stessa, è può essere schematizzata nel seguente modo: @”stringa_desiderata”. Dovrete sempre utilizzare questo formato quando istanziate una stringa. • “%@”, quando trovate un % in una stringa, significa che li ci andrà il valore di una determinata variabile. Non a caso dopo la stringa trovare la variabile “nome”: il contenuto di tale variabile nome andrà inserito al posto di %@. Se avessimo dovuto inserire il valore di una variabile di tipo float avremmo usato la sintassi %f. Vedremo parecchi esempi nei prossimi tutorial. Il metodo “dealloc”, infine, è quello che si occupa di liberare la memoria che abbiamo utilizzato. L’Objective-C, infatti, non prevede un gestore della memoria come avviene invece in Java (tramite il Garbage Collector). Sarà compito degli sviluppatori, quindi, liberare la memoria dagli oggetti che non servono più. In questo metodo dovrete sempre inserire i componenti che avete utilizzato, richiamando per ognuno il metodo “dealloc”. Nell’esempio potete vedere che liberiamo dalla memoria gli oggetti “labelSaluto” e “fieldNome”. Possiamo ora cliccare su “Build and Go!”, se non abbiamo commesso errori nell’inserire il codice si avvierà l’iPhone Simulator e potremo testare il nostro programma!

F ACCIAMO

NASCONDERE LA TASTIERA

Se provate ad inserire un nome e a premere il tasto “Invio” della tastiera che appare sull’iPhone, noterete che essa non si chiude. Si tratta di un bug? La risposta è no. È normale, in quanto non abbiamo implementato niente che chiuda tale tastiera. Per sistemare questo problema, apriamo il file “HelloWorldViewController.h” e modifichiamo l’intestazione nella seguente maniera: 1 @interface HelloWorldViewController : UIViewController <UITextFieldDelegate> {

Potete notare che abbiamo aggiunto “<UITextFieldDelegate>“, ovvero la nostra classe deve implementare il delegato della classe UITextField. Parleremo più avanti di cosa siano i delegati, per ora sappiate che sono dei comportamenti comuni a delle classi di oggetti. Fatto ciò, andiamo nel file “HelloWorldViewController.m” e inseriamo, in un qualsiasi punto, questo metodo: 1 2 3 4

-(BOOL)textFieldShouldReturn:(UITextField *)textField{ ! [textField resignFirstResponder]; ! return YES; }

Questo metodo si occuperà della chiusura della nostra tastiera. Non soffermiamoci sul codice, in quanto è così in qualsiasi occasione voi vogliate implementarlo. Salvate entrambi i file e aprite “HelloWorldViewController.xib”. Cliccate sulla UITextField e aprite il “Connections Inspector”: vedrete nella sezione “Outlets” un elemento chiamato “delegate”, prendete il pallino e

Guida pratica a!’iPhone SDK"

21


trascinatelo sul “File’s Owner” nel pannello dei documenti. Se avrete eseguito correttamente questa operazione il vostro pannello sarà come questo:

In pratica, abbiamo detto che il delegato di tale oggetto è gestito dalla classe “HelloWorldViewController”. Salvate ora il tutto e chiudete Interface Builder. Provate poi ad eseguire la vostra applicazione, tutto funzionerà in maniera corretta! Avete così creato la vostra prima applicazione funzionante per iPhone!

Guida pratica a!’iPhone SDK"

22


Capitolo 4: TrashApp, gestiamo le immagini In questo secondo tutorial, inizieremo a prendere confidenza con un aspetto molto importante: la gestione delle immagini, e come l’utente può interagire con esse. Andremo a creare, infatti, un finto cestino, in cui potremo trascinare un’immagine e ripristinarla tramite un apposito pulsante.

D EFINIAMO L ’ APPLICAZIONE Creiamo un nuovo progetto di tipo “View-Based Application” e chiamiamolo “TrashApp”. A differenza del tutorial precedente, questa volta creeremo tutto tramite Interface Builder, metodo sicuramente più veloce e comodo per applicazioni non troppo complesse. Prima di fare qualsiasi cosa, inseriamo nel nostro progetto le immagini che ci serviranno. Io utilizzerò le seguenti immagini: due per il cestino, e una per il documento da “eliminare” (potete trovare queste immagini nel file di progetto dell’esempio):

TrashIconEmpty.png

TrashIconFu!.png

windows icon.png

Trascinate le immagini nel progetto in XCode, e nel pop-up che vi apparirà mettere la spunta a “Copy items into destination group’s folder (if needed)”. Noterete ora le immagini all’interno del progetto:

Prima di definire la struttura grafica della nostra applicazione, andiamo a definire i componenti che poi ci serviranno. Apriamo il file “TrashAppViewController.h” e inseriamo le seguenti definizioni:

Guida pratica a!’iPhone SDK"

23


1 2 3 4 5 6 7 8 9 10

#import <UIKit/UIKit.h> @interface TrashAppViewController : UIViewController { ! IBOutlet UIImageView *imageCestino; ! IBOutlet UIImageView *imageLogo; } -(IBAction)ripristina; @end

Abbiamo definito gli elementi necessari: alle righe 4 e 5 due UIImageView, che conterranno il cestino (pieno o vuoto a seconda del caso) e il logo da eliminare. Alla riga 8, infine, abbiamo definito l’azione che ci permetterà di ripristinare il logo dopo la sua eliminazione.

D EFINIAMO L ’ ASPET TO

GRAFICO .

Procediamo, quindi, con la creazione della struttura grafica della nostra applicazione. Salvate il f i l e “ Tr a s h A p p Vi e w C o n t r o l l e r. h” a p p e n a m o d i f i c a t o e a p r i t e p o i “TrashAppViewController.xib”, che avvierà Interface Builder. La finestra è per ora semplice e si presenterà così:

Guida pratica a!’iPhone SDK"

24


Inseriamo, per prima cosa, gli elementi necessari: due componenti UIImageView e un UIButton. Attenzione: la prima UIImageView che inserite deve essere quella in basso, altrimenti avrete problemi nelle fasi successive! Ecco come si presenterà la vostra applicazione:

Ora dobbiamo collegare i vari componenti alle immagini che abbiamo inserito all’inizio del progetto. Clicchiamo sul primo componente UIImageView (quello più in alto, ma il secondo che avete inserito!) e apriamo il pannello “Attributes Inspector”. Nel menù a tendina “Images” selezioniamo il file “windows icon.png” e lo vedremo comparire anche nell’applicazione. Spuntiamo, inoltre, la casella “User Interaction Enabled”. Avremo un pannello così impostato:

Guida pratica a!’iPhone SDK"

25


Facciamo la stessa cosa per la UIImageView sottostante, selezionando come immagine “TrashIconEmpty.png”, ma senza spuntare “User Interaction Enabled”. Inseriamo all’interno del bottone la scritta “Ripristina logo”, aggiustiamo le dimensioni e la posizione delle due immagini (in modo che i bordi delle UIImageView coincidano con le immagini al loro interno) fino ad avere un risultato come questo:

Ora non dobbiamo fare alto che collegare gli elementi che abbiamo definito all’inizio di questo tutorial con i componenti all’interno della nostra applicazione. Dal Pannello dei Documenti selezioniamo il “File’s Owner”:

Guida pratica a!’iPhone SDK"

26


Ora apriamo il “Connections Inspector”, dovremmo vedere i seguenti elementi:

Prendiamo il pallino che troviamo a fianco di “imageLogo” e trasciniamolo sul logo di Windows, mentre quello di “imageCestino” sull’immagine del cestino. Colleghiamo, infine, l’azione: proprio come nello scorso tutorial, colleghiamo il pallino dell’azione “ripristina:” sul bottone, e nel menù che appare selezioniamo “Touch Up Inside”. Se abbiamo eseguito tutto in maniera corretta avremo un pannello come il seguente:

Abbiamo concluso questa fase del tutorial. Salviamo tutto e chiudiamo pure Interface Builder.

I MPLEMENTIAMO

IL MOVIMENTO DEL LOGO

Iniziamo aprendo il file “TrashAppViewController.h” e dichiarando un paio di elementi che ci serviranno:

Guida pratica a!’iPhone SDK"

27


1 2 3 4 5 6 7 8 9 10 11

#import <UIKit/UIKit.h> @interface TrashAppViewController : UIViewController { ! IBOutlet UIImageView *imageCestino; ! IBOutlet UIImageView *imageLogo; ! ! BOOL cancellato; } -(IBAction)ripristina; -(void)cancella;

Alla riga 7 abbiamo aggiunto una variabile che ci servirà per controllare se il nostro oggetto è già stato eliminato (quindi, al valore YES corrisponderà il logo eliminato, con NO il nostro logo sarà ancora visibile); lo stesso vale per il metodo “cancella”, che si occuperà invece dell’animazione legata all’eliminazione del logo. Ora iniziamo ad implementare i metodi necessari. Apriamo il file “TrashAppViewController.m” e inseriamo il seguente codice: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { ! UITouch *touch = [[event allTouches] anyObject]; ! if ([touch view] == imageLogo) { ! ! imageLogo.center = [touch locationInView:self.view];! ! }! ! } - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { ! if (CGRectContainsRect([imageCestino frame], [imageLogo frame])){ ! ! imageCestino.image = [UIImage imageNamed:@"TrashIconFull.png"]; ! ! [self cancella]; ! } else{ ! ! [UIView beginAnimations:nil context:NULL]; ! ! [UIView setAnimationDuration:0.5]; ! ! imageLogo.center=CGPointMake(155.0,100.0); ! ! [UIView commitAnimations]; ! } }! - (void)cancella{ ! cancellato = YES; ! [UIView beginAnimations:nil context:NULL]; ! [UIView setAnimationDuration:0.5]; ! imageLogo.transform = CGAffineTransformMakeScale(.001, .001); ! [UIView commitAnimations]; }

Guida pratica a!’iPhone SDK"

28


Abbiamo definito tre metodi, che si occuperanno del movimento del logo di Windows e della sua cancellazione. vediamoli nel dettaglio: • touchesMoved, (dalla riga 1 alla 6) In questo metodo, salviamo nella variabile “touch” l’evento che l’utente compie toccando un qualsiasi oggetto della nostra applicazione (riga 2). Controlliamo, poi, che l’oggetto toccato corrisponda a “imageLogo” (riga 3), cioè al logo di Windows: se l’oggetto è proprio quello, teniamo traccia del centro dell’oggetto (che nel frattempo viene mosso dall’utente) con la posizione del dito sullo schermo (riga 4). Ovvero, è come se spostassimo fisicamente l’oggetto con il nostro dito e lo muovessimo su un piano. • touchesEnded, (dalla riga 8 alla 18) In questo metodo diciamo semplicemente che se il frame di “imageLogo” (ovvero il logo di Windows) è contenuto in quello del cestino (riga 9), deve essere chiamato il metodo “cancella”, che si occuperà dell’animazione della cancellazione (riga 11). Prima di chiamare tale metodo, inoltre, cambiamo l’immagine del cestino vuoto con quella del cestino pieno (riga 10). Se il logo, invece, non è stato spostato sopra il cestino, eseguiamo una semplice animazione, che riporta l’immagine al centro della vista (dalla riga 13 alla 16). • cancella, (dalla riga 20 alla 26) In questo metodo definiamo l’animazione che avrà il logo di Windows quando verrà sposato sopra il cestino. Alla riga 16 cambiamo il valore della variabile “cancella”, in modo da sapere che il logo è stato eliminato. Alla riga 17 definiamo il punto di partenza della nostra animazione, mentre con l’istruzione successiva ne definiamo la durata. La riga 19 è l’animazione vera e propria, che farà scomparire il logo. Con l’ultima istruzione definiamo la fine dell’animazione.

IL

RIPRISTINO DEL LOGO

Abbiamo quasi terminato la nostra applicazione, manca solo la definizione dell’azione “ripristina:”. Tale metodo è già stato definito da Interface Builder, quindi noi dobbiamo solo scrivere il codice al suo interno. Ecco le istruzioni da inserire: 1 2 3 4 5 6 7 8 9 10

- (IBAction)ripristina{ ! if (cancellato) { ! ! [UIView beginAnimations:nil context:NULL]; ! ! [UIView setAnimationDuration:0.5]; ! ! imageLogo.transform = CGAffineTransformIdentity; ! ! imageCestino.image = [UIImage imageNamed:@"TrashIconEmpty.png"]; ! ! imageLogo.center = CGPointMake(155.0, 100.0); ! ! [UIView commitAnimations]; ! } }

Questo metodo è speculare a “cancella”, in quanto dobbiamo eseguire l’animazione inversa! Andremo, quindi, ad eseguire un’animazione, che porterà il logo dal cestino (in cui si trova) alla posizione originale (o quasi, in quanto è definita in modo arbitrario da noi, alla riga 7).

Guida pratica a!’iPhone SDK"

29


Clicchiamo ora su “Build and Go!”, e testiamo la nostra applicazione funzionante! Nota: se non avete l’animazione, controllate due cose. La prima è che il logo di Windows non si nasconda dietro il cestino. Se così fosse, non avete seguito quello che vi ho detto nella costruzione dell’Interfaccia!! Ma non disperate, vi basterà entrare in Interface Builder e scambiare l’ordine dei due componenti (ovviamente invertendo anche le immagini e le proprietà associate). La seconda, invece, che la dimensione del logo (sempre in Interface Builder) e del componente UIImageView non sia maggiore di quella del cestino, altrimenti il controllo che abbiamo scritto nel metodo “touchesEnded” fallisce e non viene lanciata l’animazione. Anche in questo caso ci basta entrare in Interface Builder e ridimensionare il componente UIImageView.

Guida pratica a!’iPhone SDK"

30


Capitolo 5: UIToolbar e auto-rotazione In questo terzo tutorial, analizzeremo un componente molto importante, la UIToolbar, e una funzionalità molto gradita agli utenti, l’auto-rotazione. Non creeremo nessuna applicazione complicata, semplicemente avremo due pulsanti nella toolbar che modificheranno il valore di una label posta al centro dello schermo. L’auto-rotazione, infine, aggiungerà un tocco più professionale alla nostra applicazione.

D EFINIAMO L ’ APPLICAZIONE Come sempre, la prima cosa che faremo è definire un nuovo progetto. Creiamo un nuovo progetto di tipo “View-Based Application” e chiamiamolo “CountRotateApp”. Procediamo proprio come abbiamo fatto nello scorso tutorial, quindi apriamo il file “CountRotateAppViewController.h” e inseriamo le seguenti dichiarazioni: 1 2 3 4 5 6 7 8 9 10

#import <UIKit/UIKit.h> @interface CountRotateAppViewController : UIViewController { ! IBOutlet UILabel *labelNumero; } -(IBAction)aggiungi; -(IBAction)sottrai; @end

Abbiamo definito una label, che ospiterà un numero, che sarà incrementato o decrementato in base al pulsante che verrà premuto (ovviamente saranno le azioni “aggiungi” e “sottrai” che si occuperanno di questo compito). Salviamo il file appena modificato e facciamo doppio clic su “CountRotateAppViewController.xib”, in cui andremo a definire l’aspetto della nostra applicazione.

D EFINIAMO L ’ ASPET TO

GRAFICO

Iniziamo inserendo nella parte bassa della vista una UIToolbar, con due UIBarButtonItem: in uno scrivete “-”, nell’altro “+”. Noterete che i due bottoni sono quasi attaccati. Noi vogliamo che siano ai due estremi, quindi tra di essi inseriamo un “Flexible Space Bar Button Item”, in modo che restino sempre separati. Ecco come si presenterà la vostra toolbar:

Questo spazio flessibile ha una grossa utilità: non solo ci separa i due bottoni, ma ci permette di non doverci occupare della giusta distanza tra essi, anche nel caso che ne aggiungessimo un

Guida pratica a!’iPhone SDK"

31


terzo. Inoltre esso ci permette di tenere i due bottoni alle estremità della barra anche nel caso in cui ruotassimo la nostra applicazione. Come facciamo a testarlo? Semplice. Cliccate sulla freccia presente nel titolo della finestra della nostra applicazione:

Vedrete che la schermata ruoterà!

E come possiamo notare i due bottoni restano agli estremi della nostra barra. Proprio il risultato che volevamo! Riportiamo la finestra alla sua posizione originale, e inseriamo al centro una UILabel, partendo da un angolo in alto a sinistra, per poi ingrandirla fino all’angolo opposto. Nell’Attribute Inspector settate i seguenti parametri: • “Text”: 0 (zero); • A!ineamento centrale; • “Font Size”: 200 Dovreste avere il seguente risultato:

Guida pratica a!’iPhone SDK"

32


Proviamo ora a far ruotare la schermata come abbiamo fatto poco fa. Noteremo che lo zero non rimane in posizione centrale, ma addirittura viene per metà nascosto. Come facciamo a lasciarlo centrato? Anche qui ci viene in aiuto l’Interface Builder, che offre grandi potenzialità anche in questo aspetto. Selezioniamo la label che contiene lo zero e apriamo il “Size Inspector”. Nella seconda parte possiamo vedere che vi è una sezione denominata “Autosizing”. Clicchiamo sulle due freccette rosse che vediamo nel riquadro piccolo, in modo da avere questo schema:

Proviamo ora a ruotare la nostra applicazione: lo zero resterà perfettamente in posizione centrale! Ora che abbiamo definito la struttura grafica dell’applicazione, non ci resta altro che collegare l’elemento e le due azioni che abbiamo definito all’inizio del tutorial. Dal Pannello dei Documenti selezioniamo il File’s Owner e spostiamoci poi nel “Controller Connections” (come abbiamo già fatto nel capitolo 4). Dovete avere un pannello come questo:

Guida pratica a!’iPhone SDK"

33


Colleghiamo “labelNumero” con l’unica label presente al centro della vista, e le due azioni ai rispettivi bottoni (al bottone “+” l’azione “aggiungi”, mentre al bottone “-” l’azione “sottrai”). Se avete eseguito tutto in maniera corretta avrete questo risultato:

Salviamo tutto e chiudiamo Interface Builder.

S CRIVIAMO

IL CODICE NECE SSARIO

Prima di iniziare ad implementare i metodi che abbiamo già definito, aggiungete questa variabile al file “CountRotateAppViewController.h”: 1 2 3 4

@interface CountRotateAppViewController : UIViewController { ! IBOutlet UILabel *labelNumero; ! int numero; }

Semplicemente, abbiamo definito una variabile intera alla riga 3, di nome “numero”, che conterrà il valore mostrato dalla label. Passiamo, quindi, al file “CountRotateAppViewController.m”. Iniziamo con questo semplice metodo (dovreste trovarlo già presente nella classe, vi basterà eliminare i commenti che lo rendono nascosto):

Guida pratica a!’iPhone SDK"

34


1 - (void)viewDidLoad { 2 ! [super viewDidLoad]; 3 ! numero = 0; 4 }

Questo metodo viene richiamato sempre all’avvio del file “.xib” associato alla classe (i file “.xib” sono quelli creati da InterfaceBuilder). In questo metodo possiamo inizializzare tutti i componenti che ci serviranno. Qui, in pratica, dobbiamo inserire tutte quelle operazioni che vogliamo vengano eseguite all’avvio dell’applicazione. Nel nostro esempio, vogliamo che la variabile “numero” sia impostata a zero. Prendete confidenza con tale metodo perchè lo incontrerete spesso nei prossimo tutorial. Aggiungiamo, ora, le implementazioni per i due metodi che si occupano di aumentare e diminuire il valore della variabile “numero”: 1 - (IBAction)aggiungi { 2 ! numero++; 3 ! labelNumero.text = [[NSString alloc] initWithFormat:@"%i",numero]; 4 } 5 6 - (IBAction)sottrai { 7 numero--; 8 ! labelNumero.text = [[NSString alloc] initWithFormat:@"%i",numero]; 9 }

Questo due metodi non eseguono niente di complesso, si limitano a incrementare (o decrementare) la variabile “numero”, per poi visualizzarla nella label. Semplice vero? L’ u l t i m a c o s a d a i m p l e m e n t a r e è l a r o t a z i o n e d e l l a v i s t a . S e m p r e n e l f i l e “CountRotateAppViewController.m” cercate e decommentate il seguente metodo (è già presente, vi basterà decommentarlo e modificare l’istruzione alla riga 2): 1 -(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientatio n)interfaceOrientation { 2 // Return YES for supported orientations 3 return YES; 4 }

Questo è un metodo della classe “UIViewController”, che implementa già la rotazione automatica dello schermo. Ancora una volta non dovremo fare veramente niente, in quanto sono le librerie del SDK a fornirci tutti pronto. Piccola nota: se non volessimo implementare l’auto-rotazione, ci basterebbe ritornare come valore “NO”, oppure semplicemente non inserire il metodo nell’applicazione.

Guida pratica a!’iPhone SDK"

35


Clicchiamo ora su “Build and Go!” e testiamo la nostra applicazione!

Guida pratica a!’iPhone SDK"

36


Capitolo: 6: NSTimer e UIProgressView Proseguiamo la panoramica sui componenti più utilizzati nella creazione di applicazioni per iPhone. In questo capitolo vedremo come utilizzare la classe NSTimer, ovvero un temporizzatore, che ci permetterà di eseguire animazioni e transizioni con durate predefinite. Utilizzeremo, inoltre, la UIProgressView, ovvero la barra di progresso, necessaria quando si deve mostrare un caricamento. Quella che andremo a creare sarà una semplice applicazione, che permetterà all’utente di cambiare il colore dello sfondo, semplicemente cliccando su un bottone. Il cambio del colore, inoltre, avverrà in maniera graduale tramite un’animazione della durata di 10 secondi.

D EFINIAMO L ’ APPLICAZIONE Come sempre, iniziamo creando un progetto di tipo “View-Based Application” e chiamiamolo “ProgressColour”. Apriamo il file “ProgressColourViewController.h” e definiamo i seguenti componenti: 1 2 3 4 5 6 7 8 9 10 11

#import <UIKit/UIKit.h> @interface ProgressColourViewController : UIViewController { ! IBOutlet UILabel *progressLabel; ! IBOutlet UIProgressView *progressBar; } -(IBAction)caricamentoBlu; -(IBAction)caricamentoRosso; @end

La label definita alla riga 4 servirà per mostrare un messaggio all’utente sul grado di completamento dell’animazione, mentre la UIProgressBar darà la stessa informazioni ma in maniera più visiva (è una classica barra di caricamento). Le due azioni (righe 8 e 9) dovranno essere associate a due bottoni, che avvieranno il cambio di colore dello sfondo. Possiamo ora iniziare a definire l’aspetto grafico dell’applicazione, aprendo il file “ProgressColourViewController.xib”.

D EFINIAMO L ’ ASPET TO

GRAFICO

Inseriamo nella nostra vista i primi due componenti necessari: una UILabel e una UIProgressView. Ricreate una disposizione simile a questa (ovviamente nessuno vi vieta di personalizzarla a vostro piacimento):

Guida pratica a!’iPhone SDK"

37


Come potete notare la label e la barra di progresso occupano quasi per intero la larghezza della vista, questo per rendere più evidente ciò che avviene. Selezioniamo la label e apriamo “Attributes Inspector”, per modificare alcune proprietà: • cancellate il contenuto del campo “Text”; • “Font Size”: 20 • allineamento centrale. Selezioniamo ora la UIProgressView e, sempre in “Attributes Inspector”, impostiamo il valore della casella “Progress” a zero. Inseriamo ora nella vista due bottoni, in modo da avere un risultato finale come questo:

Guida pratica a!’iPhone SDK"

38


Abbiamo già concluso la creazione della parte grafica della nostra applicazione. Non ci resta che collegare i componenti che abbiamo definito ad inizio tutorial. Dal Pannello dei Documenti selezioniamo, come sempre, il “File’s Owner” e apriamo il “Connections Inspector”. Dovreste avere un pannello così composto:

Colleghiamo l’elemento “progressLabel” con la label vuota presente sopra la barra, e “progressBar” con la barra stessa. Colleghiamo,poi, anche le due azioni: “caricamentoBlu” andrà sul bottone più in basso, quello con il testo “Applica sfondo blu”, mentre “caricamentoRosso” con l’altro bottone. Se avete eseguito tutto in maniera corretta dovreste avere questo risultato:

Abbiamo così terminato questa fase. Salviamo e chiudiamo Interface Builder.

S CRIVIAMO

IL CODICE

Dobbiamo definire un elemento e un paio di metodi che non abbiamo scritto inizialmente. Apriamo il file “ProgressColourViewController.h” e inserite le dichiarazioni mancanti:

Guida pratica a!’iPhone SDK"

39


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

#import <UIKit/UIKit.h> @interface ProgressColourViewController : UIViewController { ! IBOutlet UILabel *progressLabel; ! IBOutlet UIProgressView *progressBar; ! ! NSTimer *timer; } @property (nonatomic, retain) NSTimer *timer; -(IBAction)caricamentoBlu; -(IBAction)caricamentoRosso; -(void)aggiornaBlu; -(void)aggiornaRosso; -(void)applicaBlu; -(void)applicaRosso; @end

Abbiamo definito un componente “NSTimer” (alla riga 7), che sarà il temporizzatore che ci permetterà di eseguire l’animazione prevista. Sono stati dichiarati, inoltre, quattro nuovi metodi, che ci serviranno per implementare tutte le azioni necessarie (dalla riga 12 alla 15). Passiamo ora al file “ProgressColourViewController.m” e iniziamo ad implementare i metodi necessari. Inseriamo il seguente codice: 1 2 3 4 5 6 7 8 9 10

#import "ProgressColourViewController.h" @implementation ProgressColourViewController @synthesize timer;

- (IBAction)caricamentoBlu { progressBar.progress = 0.0; ! progressLabel.text = @"Caricamento colore..."; ! timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(aggiornaBlu) userInfo:nil repeats:YES]; 11 } 12 13 - (IBAction)caricamentoRosso { 14 ! progressBar.progress = 0.0; 15 ! progressLabel.text = @"Caricamento colore..."; 16 ! timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(aggiornaRosso) userInfo:nil repeats:YES];! 17 }

Questi due metodi sono praticamente identici, quindi mi limiterò a commentare solamente il primo. Alla riga 8 viene settato il valore di progresso della barra a zero (tale valore di default va da 0.0 a 1.0, ma questo intervallo può essere modificato a piacere). Nella riga 9 inseriamo un

Guida pratica a!’iPhone SDK"

40


messaggio nella label, in modo da comunicare all’utente ciò che sta avvenendo. L’istruzione presente alla riga 10, infine, è quella che merita più attenzione. Viene definita la variabile timer, istanziandola con la classe NSTimer. Ci sono tre parametri molto importanti in questa funzione: la durata di 1 secondo (alla clausola “scheduledTimerWithTimeInterval”), il metodo che deve essere eseguito ad ogni ripetizione (clausola “@selector()”) e la ripetizione continua di tale intervallo di tempo (impostata tramite “repeats:YES“). Proseguiamo con la definizione dei metodi: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23

- (void)aggiornaBlu{ ! progressBar.progress = progressBar.progress + 0.1; ! if (progressBar.progress == 0.5){ ! ! progressLabel.text = @"Applicando colore..."; ! ! [self applicaBlu]; ! } ! if (progressBar.progress == 1.0){ ! ! progressLabel.text = @"Colore applicato!"; ! ! [timer invalidate]; ! } } - (void)aggiornaRosso{ ! progressBar.progress = progressBar.progress + 0.1; ! if (progressBar.progress == 0.5){ ! ! progressLabel.text = @"Applicando colore..."; ! ! [self applicaRosso]; ! } ! if (progressBar.progress == 1.0){ ! ! progressLabel.text = @"Colore applicato!"; ! ! [timer invalidate]; ! } }

Anche questi due metodi sono praticamente uguali. Alla riga 2 incrementiamo il valore della nostra barra di progresso, aumentandone il valore del 10%. Alla riga 3 troviamo un controllo if, che verifica se il valore della barra è 0.5 (ovvero siamo a metà): in caso affermativo, cambiamo il testo presente nella label, altrimenti lasciamo tutto invariato. Anche alla riga 7 un ciclo if controlla se la barra di progresso è arrivata al suo valore massimo: in tal caso inseriamo un nuovo testo nella label, e fermiamo il timer (con l’istruzione alla riga 9). Nel primo ciclo if che abbiamo esaminato, notiamo che alla riga 5 viene richiamato il metodo “applicaBlu”: tale metodo avrà il compito di cambiare il colore allo sfondo della vista, con un’animazione che dovrà durare 5 secondi (infatti siamo al 50% del progresso, e la barra avanza del 10% ogni secondo). Ecco i due metodi che si occupano di fare ciò:

Guida pratica a!’iPhone SDK"

41


1 2 3 4 5 6 7 8 9 10 11 12 13

- (void)applicaBlu{ ! [UIView beginAnimations:nil context:NULL]; ! [UIView setAnimationDuration:5.0]; ! self.view.backgroundColor = [UIColor blueColor]; ! [UIView commitAnimations]; } - (void)applicaRosso{ ! [UIView beginAnimations:nil context:NULL]; ! [UIView setAnimationDuration:5.0]; ! self.view.backgroundColor = [UIColor redColor]; ! [UIView commitAnimations]; }

In questi due metodi viene definita l’animazione che permette allo sfondo della nostra vista di cambiare colore. L’animazione rispecchia molto quella illustrata in un capitolo precedente. Alla riga 3 definiamo la durata di tale animazione (5 secondi); l’istruzione successiva è il risultato che vogliamo ottenere, ovvero il nostro colore di sfondo. Chiude il gruppo di istruzioni la riga 5, che avvia l’animazione. Clicchiamo su “Build and Go!” e testiamo la nostra applicazione!

Guida pratica a!’iPhone SDK"

42


Capitolo 7: AccessContact, accediamo alla rubrica In questo capitolo andremo ad implementare una funzione un po’ particolare, in quanto accederemo all’applicazione nativa “Contatti” e ricaveremo le informazioni di un contatto. Impareremo ad utilizzare il framework (una sorta di libreria, che ci fornisce delle funzionalità già pronte) “AddressBook” e come sfruttare le funzioni che ci mette a disposizione.

D EFINIAMO

IL PROGET TO

Iniziamo creando un progetto del tipo “View-Based Application” e chiamiamolo “AccessContact”. Questa volta procederemo come nel primo tutorial, ovvero andremo a definire prima i componenti via codice, poi li collegheremo tramite Interface Builder. Apriamo il file “AccessContactViewController.h”, che è la classe della vista che ci viene fornita con questo template. Inseriamo il seguente codice: 1 2 3 4 5 6 7 8 9 10 11 12 13

#import <UIKit/UIKit.h> #import <AddressBook/AddressBook.h> #import <AddressBookUI/AddressBookUI.h> @interface AccessContactViewController : UIViewController { ! IBOutlet UILabel *labelNome; ! IBOutlet UILabel *labelCognome; ! IBOutlet UILabel *labelTel; } - (IBAction)getContatto; @end

Ormai siete esperti, e avrete subito capito che abbiamo definito tre label e un’azione. Alle righe 2 e 3, però, abbiamo importato due librerie, che si riferiscono ad “AddressBook”, ovvero all’applicazione “Contatti”. Questo, però, non basta per poter utilizzare tutte le sue funzioni. Dobbiamo importare all’interno del nostro progetto anche il framework necessario. Espandete la sezione “Targets” nel progetto, e cliccate con il tasto destro su “AccessContact”, selezionando poi “Get Info”. Si aprirà una nuova schermata, in cui dobbiamo andare nella sezione “General”. Nell’angolo in basso a sinistra noteremo un bottone “+”, clicchiamo e si aprirà un elenco di tutti i framework disponibili:

Guida pratica a!’iPhone SDK"

43


Selezioniamo “AddressBook.framework” e “AddressBookUI.framework” e clicchiamo poi su “Add”. Avremo così aggiunto questi due framework al nostro progetto. Possiamo così chiudere la schermata delle proprietà. S a l v i a m o i l f i l e “Ac ce s s C o n t a c t Vi e w C o n t r o l l e r. h” e f a c c i a m o d o p p i o c l i c s u “AccessContactViewControlle.xib” per aprire Interface Builder.

D EFINIAMO

LA STRUT TURA GRAFICA

Dobbiamo ora definire l’aspetto grafico della nostra applicazione. Inseriamo le label necessarie e un bottone, per ricreare un aspetto grafico come questo:

Guida pratica a!’iPhone SDK"

44


Le label con il testo “---” sono quelle che poi conterranno le informazioni sul contatto selezionato dall’utente. Dobbiamo ora collegare gli elementi definiti in precedenza con quelli che abbiamo appena inserito nella vista. Tramite il pannello dei documenti selezioniamo “File’s Owner”, e apriamo il “Connections Inspector”. Potremo vedere i componenti che abbiamo dichiarato:

Ora dobbiamo collegarli nella maniera corretta, ovviamente in base al nome con cui li abbiamo chiamati: “labelNome”, quindi, andrà collegata con la label a fianco di “Nome” e così via. L’azione “getContatto”, invece, sarà da collegare al bottone, scegliendo come sempre “Touch Up Inside” tra le azioni disponibili. Ecco il risultato finale dei collegamenti:

Possiamo salvare tutto e chiudere Interface Builder.

S CRIVIAMO

IL CODICE NECE SSARIO

Dobbiamo ora implementare i metodi necessari per far funzionare l’applicazione. Iniziamo con la definizione del metodo “getContatto”, ovvero l’azione collegata alla pressione del bottone. Apriamo il file “AccessContactViewController.m” e inseriamo il seguente codice:

Guida pratica a!’iPhone SDK"

45


1 -(IBAction)getContatto { 2 ! //Crea l’oggetto necessario 3 ! ABPeoplePickerNavigationController *picker = [[ABPeoplePickerNavigationController alloc] init]; 4 ! //Il delegato dell’oggetto è definito nella classe stessa 5 ! picker.peoplePickerDelegate = self; 6 ! //Visualizza l’app Contatti 7 ! [self presentModalViewController:picker animated:YES]; 8 ! //Rilascia l’oggetto 9 ! [picker release]; 10 }

Come si può leggere dai commenti, questo metodo istanzia un oggetto chiamato “picker”, che ci permetterà di aprire l’applicazione nativa “Contatti”. Alla riga 5 definiamo il delegato di tale oggetto: impostando “self”, comunichiamo che sarà la stessa classe (ovvero “AccessContactViewController”) a definire gli altri metodi necessari, che definiremo tra poco. Alla riga 7, infine, inseriamo tale oggetto come vista principale della nostra applicazione: l’utente vedrà così comparire l’applicazione nativa “Contatti” all’interno della nostra applicazione “AccessContact”. Dobbiamo ora implementare i metodi richiesti dal delegato. Ecco il codice da inserire: 1 - (BOOL)peoplePickerNavigationController: (ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person { 2 ! //Settiamo il nome 3 labelNome.text = (NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty); 4 ! //Settiamo il cognome 5 labelCognome.text = (NSString *)ABRecordCopyValue(person, kABPersonLastNameProperty);! 6 ! //Settiamo il numero di telefono 7 ! ABMultiValueRef multi = ABRecordCopyValue(person, kABPersonPhoneProperty); 8 ! labelTel.text = (NSString*)ABMultiValueCopyValueAtIndex(multi, 0); 9 ! //Rimuove il controller "Contatti" 10 [self dismissModalViewControllerAnimated:YES];! 11 return NO; 12 } 13 14 15 (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavig ationController *)peoplePicker { 16 // facciamo tornare il controller alla vista principale 17 ! [self dismissModalViewControllerAnimated:YES]; 18 }

Il primo metodo legge le informazioni del contatto selezionato, e le setta nelle apposite label. L’unico inconveniente è dato dalle righe 7 e 8, che si occupano della lettura del numero di tele-

Guida pratica a!’iPhone SDK"

46


fono: viene letto il primo numero presente (in quanto potrebbero anche esserci più numeri). E se non vi fosse nessun numero associato al contatto? In tal caso l’applicazione crasha. Questo avviene perché non abbiamo effettuato nessun controllo, ma potete semplicemente risolvere questo problema tramite un opportuno ciclo if. Il metodo che inizia alla riga 15, infine, si occupa di chiudere l’applicazione “Contatti” quando l’utente sceglie di uscire senza selezionare nessun contatto (ovvero quando clicca su “Cancel”). Potete notare che l’istruzione di tale metodo è uguale a quella presente alla riga 10, che è uguale a sua volta a quella presente alla riga 7 del primo metodo implementato. Cliccate su “Build and Go!” e testate la vostra applicazione!

Guida pratica a!’iPhone SDK"

47


Capitolo 8: Creiamo un mini browser con le UIWebView Una delle caratteristiche principali dell’iPhone è la sua connettività, sia essa tramite WiFi, 3G o EDGE. Internet, quindi, ricopre un ruolo fondamentale nell’utilizzo di questo dispositivo. Ecco che sorge spesso necessario implementare una sorta di browser nelle nostre applicazioni, per poter visualizzare delle pagine web. Anche in questo l’SDK si rivela molto potente, in quanto ci mette a disposizione un componente praticamente già pronto: le UIWebView. Questo componente è una sorta di “Safari lite”, in quanto ci permette di visualizzare pagine web tramite lo stesso motore che è alla base di Safari. Nel tutorial vedremo come utilizzare le UIWebView, per realizzare un nostro mini-browser, con tre semplici pulsanti: avanti, indietro e ricarica. Certo, non potremo competere con Safari, ma potrebbe tornarvi molto utile nei vostri programmi.

C REIAMO

LA STRUT TURA GRAFICA

Iniziamo creando un nuovo progetto di tipo “View-Based Application” e chiamiamolo “MyBrowser”. Prima di definire l’aspetto della nostra applicazione, dichiariamo un componente che ci servirà (sarà il componente principale che caricherà le pagine web). Apriamo il file “MyBrowserViewController.h” e inseriamo la seguente definizione: 1 @interface MyBrowserViewController : UIViewController { 2 IBOutlet UIWebView *webView; 3 } 4 5 @end

Salviamo il file e apriamo “MyBrowserViewController.xib” per avviare Interface Builder. Il template che abbiamo utilizzato ci fornisce già una vista di base, noi iniziamo inserendo nella parte bassa della vista un componente di tipo UIToolbar e tre bottoni (UIBarButtonItem, quelli utilizzati nel capitolo 5), separando gli ultimi due tramite un “Flexible Space” (anche questo già visto). I primi due bottoni ci serviranno per muoverci tra le pagine visitate (i classici “Avanti” e “Indietro”), mentre il terzo servirà a ricaricare la pagina. Ecco come appare la barra appena definita:

Ora dobbiamo inserire la WebView. Dalla libreria scegliamo un componente “UIWebView” e inseriamolo nella nostra finestra. Ecco il risultato finale:

Guida pratica a!’iPhone SDK"

48


D EFINIAMO

I COMP ONENTI E COLLEGHIAMO LE AZIONI

Abbiamo già concluso con la definizione dell’interfaccia grafica. Dobbiamo ora definire i componenti che ci serviranno e collegare le relative azioni. Vedrete che si rivelerà tutto molto semplice, in quanto troveremo già tutto pronto. Iniziamo cliccando sul “File’s Owner” (che troviamo nel Pannello dei documenti). Colleghiamo il componente “webView” (che è quello definito all’inizio del tutorial) con la UIWebView che abbiamo appena inserito nella nostra applicazione. Se abbiamo eseguito questo passaggio correttamente avremo un pannello “Connections Inspector” come questo:

Dopo aver fatto questo semplice collegamento, andiamo ancora nel Pannello dei documenti ed espandiamo il componente View e selezioniamo la UIWebView :

Guida pratica a!’iPhone SDK"

49


Andiamo nel “Connections Inspector” e noteremo che ci sono già delle azioni definite (“goBack”, “goForward”, etc.), non dovremo far altro che collegarle con i bottoni adeguati. Ecco le associazioni da fare: • “goBack” con il bottone “<“, ovvero per tornare alla pagina precedente; • “goForward” con il bottone “>”, ovvero per andare alla pagina successiva (della cronologia); • “reload” con il bottone “Ricarica”, per ricaricare la pagina web. Se avete eseguito tutto correttamente avrete un risultato come questo:

Tutto molto semplice e veloce! Salviamo tutto e chiudiamo Interface Builder.

Guida pratica a!’iPhone SDK"

50


S CRIVIAMO

IL CODICE PER APRIRE LA PAGINA DE SIDERATA

Dobbiamo ora inserire il codice che si occupa di caricare la pagina web desiderata e mostrarla nella UIWebView. Utilizziamo un metodo che viene caricato all’avvio dell’applicazione, e che ci permette di settare i comportamenti iniziali del nostro browser. Aprite il file “MyBrowserViewController.m” e inserite il seguente codice: 1 2 3 4 5 6 7 8 9

- (void)viewDidLoad{ ! //indirizzo web da caricare ! NSString *indirizzo = @"http://www.bubidevs.net"; ! //crea un oggetto URL ! NSURL *url = [NSURL URLWithString:indirizzo]; ! NSURLRequest *requestObj = [NSURLRequest requestWithURL:url]; ! // visualizza la pagina nella UIWebView ! [webView loadRequest:requestObj]; }

Come potete vedere si tratta solo di quattro istruzioni! Definiamo, alla riga 3, l’indirizzo che vogliamo aprire, mentre alle righe 5 e 6 inizializiamo i componenti necessari per poter visualizzare la pagina (non preoccupatevi troppo, sono sempre questi da utilizzare). All’istruzione 8, infine, settiamo i componenti che abbiamo appena creato nella UIWebView, in modo che venga mostrata la pagina web all’utente. E se volessimo caricare dei file HTML che abbiamo in locale? Semplice, modificate così le istruzioni alle righe 3 e 5: 2 ! //indirizzo web da caricare! 3 ! NSString *indirizzo = [[NSBundle mainBundle] pathForResource:@"index" ofType:@"html"]; 4 ! //crea un oggetto URL 5 ! NSURL *url = [NSURL fileURLWithPath:indirizzo];

in questo modo caricherà il file "index.html" che si deve trovare, però, nella stessa cartella in cui viene seguita l’applicazione (quindi dovete prima importarla nel vostro progetto). Semplice vero? Cliccate su “Build and Go!” e provate il vostro personalissimo browser!

Guida pratica a!’iPhone SDK"

51


Guida pratica a!â&#x20AC;&#x2122;iPhone SDK"

52


Capitolo 9: UITableView, gestiamo le tabelle Fino ad ora abbiamo analizzato dei componenti base, molto semplici sia da impostare che da utilizzare. Il componente più utilizzato, però, è sicuramente quello che gestisce le tabelle, ovvero la UITableView. In moltissime applicazioni, infatti, esse vengono utilizzate per mostrare delle informazioni all’utente, che può anche interagire con questi dati. In questo capitolo vedremo come definire una tabella, come inserire al suo interno dei valori e come definire dei comportamenti (ad esempio la cancellazione delle righe), necessari per renderla utilizzabile dall’utente. Questo capitolo è suddiviso in tre parti: 1.Creazione e definizione de!a tabe!a; 2.Inserimento di alcune funzionalità; 3.Implementazione de!a ricerca. Analizzeremo queste parti una alla volta, passo per passo, in modo da comprendere bene ogni singola cosa che andremo a realizzare.

P ARTE 1:

CREIAMO E DEFINIAMO LA TABELLA

La prima parte di questo tutorial è dedicata alla creazione della struttura dell’applicazione: ne definiremo la grafica, la lista degli elementi da visualizzare e come mostrarli all’interno delle celle. Il tutto sarà fatto con la solita semplicità, sfruttando tutte le caratteristiche che XCode e l’SDK ci mettono a disposizione, semplificando il nostro lavoro.

C REIAMO

UN NUOVO PROGET TO

Aprimo Xcode, selezioniamo “File -> New Project”. Nel menù che ci appare selezioniamo “Navigation-based Application”, clicchiamo su “Choose…” e immettiamo come nome “tableViewTutorial” e fate clic su “Save”. Abbiamo così creato il nostro nuovo progetto. Questo template di XCode ci fornisce già una tabella con una barra di navigazione, semplificandoci notevolmente il lavoro! Nota: questo tutorial funziona con SDK 3.0 e superiori. Aprendo il file "RootViewController.xib" con Interface Builder possiamo notare la struttura già pronta, non dovremo toccare niente!

Guida pratica a!’iPhone SDK"

53


I NSERIAMO

IL CODICE NECE SSARIO

A differenza di tutti i passaggi che dovevano essere eseguiti fino al SDK 2.x, dovremo solamente inserire poche righe di codice per avere la nostra tabella già pronta e funzionante! Apriamo il file "RootViewController.h" e inseriamo la dichiarazione del seguente componente: 1 2 3 4 5 6 7

@interface RootViewController : UITableViewController { ! NSMutableArray *lista; } @property (nonatomic, retain) NSMutableArray *lista; @end

Abbiamo definito un array in cui inseriamo tutti gli elementi che devono poi essere visualizzati nella tabella. Notate che abbiamo utilizzato un NSMutableArray, questo perché dovremo avere la possibilità di poter modificare gli elementi che lo compongono (analizzeremo meglio questo aspetto quando sarà necessario). Spostiamoci ora nel file “RootViewController.m” e iniziamo inserendo queste istruzioni:

Guida pratica a!’iPhone SDK"

54


1 2 3 4 5 6 7 8 9 10 11 12 13

#import "RootViewController.h" @implementation RootViewController @synthesize lista; - (void)viewDidLoad { [super viewDidLoad]; ! ! self.title = @"Prodotti Apple"; ! ! //elementi da visualizzare nella tabella ! ! lista = [[NSMutableArray alloc] initWithObjects: @"iPhone", @"iPod",@"iPod Touch", @"iMac", @"iBook", @"MacBook", @"MacBook Pro", @"Mac Pro", @"PowerBook", nil];!

14 15

// Uncomment the following line to display an Edit button in the navigation bar for this view controller. 16 // self.navigationItem.rightBarButtonItem = self.editButtonItem; 17 }

Analizziamo quello che abbiamo appena scritto. Chi ha già un pochino di esperienza con la programmazione per iPhone conoscerà certamente il metodo “viewDidLoad“: questo viene eseguito subito dopo il caricamento della vista, e ci permette di settare tutte le variabili e tutti i parametri all’avvio. Per prima cosa abbiamo impostato il titolo alla nostra tabella, che apparirà nella NavigationBar presente nella vista (riga 10). Subito dopo viene inizializzata la lista (che è un oggetto NSMutableArray), inserendoci alcuni elementi (riga 13). Per ora non fate caso alle righe 15 e 16, ci saranno utili nella seconda parte del tutorial. Ora dobbiamo definire i metodi che si occupano di popolare la tabella. Scorrendo il file “RootViewController.m” li troverete già (XCode li inserisce sempre di default), dovete solo completarli. Iniziamo definendo i seguenti due: 1 2 3 4 5 6 7

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; }

// Setta il numero di righe della tabella . - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 8 return [lista count]; 9 }

Il primo metodo che incontriamo è “numberOfSectionsInTableView“. Se provate a modificare questo valore, vedrete che (quando eseguirete l’applicazione) la lista degli oggetti sarà ripetuta più volte. Provare per credere! A cosa serve? Nel caso in cui vogliate creare una tabella suddivi-

Guida pratica a!’iPhone SDK"

55


sa in più sezioni, ad esempio come quella dell’applicazione nativa “Contatti”, che suddivide gli elementi in ordine alfabetico. Il secondo è “numberOfRowInSection“, e setta il numero di celle in ogni sezione (nel nostro esempio avremo una sola sezione). Questo valore deve corrispondere al numero di elementi che vogliamo inserire nella tabella, quindi quelli contenuti nell’oggetto “lista”. Ci resta solamente da inserire un metodo, quello che si occupa di inserire gli elementi nelle celle della tabella. Ecco il metodo in questione: 1 // Setta il contenuto delle varie celle 2 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ 3 ! 4 ! UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cellID"]; 5 ! 6 ! if (cell == nil){ 7 ! ! cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:@"cellID"] autorelease]; 8 ! ! //setta lo stile con cui vengono selezionate le righe 9 ! ! cell.selectionStyle = UITableViewCellSelectionStyleNone;! 10 11 ! } 12 ! //inseriamo nella cella l'elemento della lista corrispondente 13 ! cell.textLabel.text = [lista objectAtIndex:indexPath.row]; 14 ! return cell; 15 }

Questo è il metodo (fondamentale ed obbligatorio) che si occupa di settare in maniera corretta le celle della tabella. Alla riga 4 troviamo la dichiarazione di una cella, che viene poi allocata alla riga 7. Con l’istruzione presente alla riga 9 definiamo come deve essere l’aspetto delle righe quando vengono selezionate dall’utente. Con questa istruzione l’utente non potrà selezionare nessuna riga, se invece la togliamo avremo la classica selezione con sfondo blu. Alla riga 13, infine, settiamo il valore contenuto nella cella: esso deve essere letto dall’array, nella posizione uguale a quella della riga (ricordatevi che sia la numerazione dell’array che delle celle parte da zero). Cliccate ora su “Build and Go!”: la nostra tabella inizia a prendere forma!

Guida pratica a!’iPhone SDK"

56


P ARTE 2: I NSERIAMO ALCUNE

FUNZIONALITÀ

Abbiamo visto come definire una tabella. In questa seconda parte vedremo come aggiungere due funzionalità davvero molto importanti: la cancellazione delle singole celle e la possibilità di renderle selezionabili. Vedrete che per entrambe le caratteristiche dovremo inserire davvero poco codice, in quanto è già tutto definito.

P ERMET TIAMO

LA CANCELLAZIONE DI UNA RIGA

La prima cosa da fare è inserire il bottone che permette di accedere alla modifica della tabella. Per fare ciò ci basta decommentare una riga che dovreste già trovare nel metodo viewDidLoad: 1 2 3 4 5 6 7 8 9

#import "RootViewController.h" @implementation RootViewController @synthesize lista;

- (void)viewDidLoad{ [super viewDidLoad]; ! // codice aggiunto nella prima parte del tutorial ... 15 // Uncomment the following line to display an Edit button in the navigation bar for this view controller. 16 self.navigationItem.rightBarButtonItem = self.editButtonItem; 17 }

Tutto molto semplice e veloce grazie alle API di Apple.

Guida pratica a!’iPhone SDK"

57


Se provate ad eseguire l'applicazione noterete che cancellando una riga essa non viene rimossa dalla tabella. Questo avviene perché non abbiamo ancora concluso di implementare questa funzionalità. In s e r i a m o , quindi, il seguente metodo: 1 // Elimina l'elemento dalla tabella e dalla lista 2 - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { 3 ! 4 ! //controlla se l'azione compiuta è un'eliminazione 5 ! if (editingStyle == UITableViewCellEditingStyleDelete) { 6 ! ! //elimina l'elemento dalla lista 7 ! ! [lista removeObjectAtIndex:indexPath.row]; 8 ! ! //elimina le'elemento dalla tabella 9 ! ! [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] 10 withRowAnimation:UITableViewRowAnimationFade]; ! ! 11 ! } 12 }

Come possiamo notare dalla struttura un po’ complicata, questo è un metodo del protocollo UITableView, proprio come quello che abbiamo implementato nella prima parte. Il costrutto if (riga 5) esegue un controllo che, come spiega il commento, controlla se l’azione eseguita sulla tabella è di cancellazione di una riga. Direte voi: “Cosa posso fare d’altro?” Per ora niente, perché la nostra tabella supporta solo l’eliminazione di una riga, ma volendo si potrebbe implementare anche l’inserimento di una nuova riga, oppure altre azioni. È sempre questo metodo che si occupa di gestire tutte le azioni sulla tabella. Ecco spiegata la necessità di questo controllo. Tornando al codice, all’interno dell’if possiamo notare due istruzioni, che eliminano l’elemento sia dalla lista (riga 7) che dalla tabella (riga 9). In questo modo la cancellazione di una riga è davvero implementata.

R ENDIAMO

LE CELLE SELEZIONABILI

Vediamo ora di implementare un’altra funzione. Vogliamo che quando l’utente seleziona una cella appaia un pop-up che contenga il nome dell’elemento selezionato. Ovviamente questa azione non ha una grande utilità, ma vi permetterà di imparare come gestire le selezioni dell’utente e vedrete, inoltre, come creare un pop-up. Prima di implementare il metodo necessario, eliminate dal metodo tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath;

la seguente istruzione (vi ho spiegato nella prima parte a cosa serviva): 1 cell.selectionStyle = UITableViewCellSelectionStyleNone;

altrimenti le celle non saranno selezionabili.

Guida pratica a!’iPhone SDK"

58


Nel solito file “RootViewController.m” inserite ora questo metodo: 1 // Se selezioniamo una riga appare un pop-up con l'elemento in questione 2 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 3 ! UIAlertView *popUp = [[UIAlertView alloc] initWithTitle:@"Hai selezionato:" message:[lista objectAtIndex:indexPath.row] delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil]; 4 ! [popUp show]; 5 ! [popUp release]; 6 }

Questo è il metodo che si occupa di eseguire una certa azione quando l’utente seleziona una cella. Alla riga 3 possiamo notare la definizione del pop-up, che conterrà un messaggio con il nome della cella selezionata. È possibile creare pop-up con diversi bottoni o più messaggi, vi basterà guardare la documentazione per trovare tutte le varianti possibili. Alla riga 6, infine, viene mostrato il pop-up appena definito. Cliccate ora su “Build and Go!” e testate la nuova tabella!

Guida pratica a!’iPhone SDK"

59


P ARTE 3: I MPLEMENTIAMO

LA RICERCA

Nella terza e ultima parte di questo lungo tutorial dedicato alle tabelle, vedremo come aggiungere un box di ricerca. Il comportamento sarà del tutto simile a quello della ricerca presente nell’applicazione nativa “Contatti”. Non sarà un compito semplicissimo, però vi potrà tornare utile in moltissime applicazioni, quindi cercate di capire il più possibile!

A GGIUNGIAMO

IL BOX DI RICERCA

Prima di lavorare con Interface Builder, apriamo il file “RootViewController.h” e dichiariamo il seguente elemento: 1

IBOutlet UISearchBar *barraRicerca;

Salviamo il file e facciamo doppio clic su “RootViewController.xib” per aprire IB, in cui inseriremo l’elemento grafico necessario: una “UISearchBar”, ottenendo un risultato come questo:

Ovviamente questa è la soluzione più semplice, volendo potreste inserire un bottone che, quando premuto, fa apparire la barra, oppure integrare il box di ricerca direttamente nella UINavigationBar principale. Ora dobbiamo definire questo elemento e le sue proprietà. Dal pannello dei documenti selezioniamo il “File’s Owner” e apriamo “Connections Inspector”. Nella sezione “Outlets” colleghiamo l’elemento “barraRicerca” con la UISearchBar che abbiamo appena inserito. Se avrete eseguito tutto correttamente avrete un risultato come questo:

Guida pratica a!’iPhone SDK"

60


Dobbiamo, infine, eseguire un ultimo collegamento. Clicchiamo sulla barra di ricerca e apriamo poi il “Connections Inspector”. Colleghiamo l’elemento “delegate” con il “File’s Owner”. Ecco come deve apparire il pannelo dopo tale collegamento:

Salviamo tutto e chiudiamo Interface Builder.

M ODIFICHIAMO

I METODI GIÀ E SISTENTI

Prima di implementare la ricerca vera e propria, dobbiamo fare delle piccole modifiche ai metodi già presenti nel nostro progetto. Iniziamo aprendo il file “RootViewController.h” e completiamo così la definizione della classe: 1 2 3 4 5 6 7 8 9 10 11 12 13

@interface RootViewController : UITableViewController { ! NSMutableArray *lista; ! NSMutableArray *filteredListContent; ! ! IBOutlet UISearchBar *barraRicerca; } @property (nonatomic, retain) NSMutableArray *lista; @property (nonatomic, retain) UISearchBar * barraRicerca; @property (nonatomic, retain) NSMutableArray *filteredListContent; @end

Guida pratica a!’iPhone SDK"

61


Alla riga 5 c’è la definizione della barra di ricerca che abbiamo inserito all’inizio di questo terzo tutorial. Alla riga 3, invece, abbiamo dichiarato una nuova lista, che conterrà gli elementi “filtrati”, ovvero quelli che corrispondono al criterio di ricerca. Ora dobbiamo modificare i metodi che si occupano dell’inizializzazione della tabella. Iniziamo dal metodo “viewDidLoad” e dalla funzione @synthetize: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

@synthesize lista, barraRicerca, filteredListContent; - (void)viewDidLoad { [super viewDidLoad]; ! ! self.title = @"Prodotti Apple"; ! ! //elementi da visualizzare nella tabella ! lista = [[NSMutableArray alloc] initWithObjects:@"iPhone", @"iPod", @"iPod Touch", @"iMac", @"iBook", @"MacBook", @"MacBook Pro", @"Mac Pro", @"PowerBook", nil]; // Uncomment the following line to display an Edit button in the navigation bar for this view controller. self.navigationItem.rightBarButtonItem = self.editButtonItem; ! ! // crea la lista filtrata, inizializzandola con il numero di elementi dell'array "lista" ! filteredListContent = [[NSMutableArray alloc] initWithCapacity: [lista count]]; ! //inserisce in questa nuova lista gli elementi della lista originale ! [filteredListContent addObjectsFromArray: lista]; ! ! // disabilita l'autocorrezione (nel box di ricerca) ! barraRicerca.autocorrectionType = UITextAutocorrectionTypeNo; ! // disabilita la prima lettera maiuscola (nel box di ricerca) ! barraRicerca.autocapitalizationType = UITextAutocapitalizationTypeNone; ! // nasconde il bottone per uscire dalla ricerca ! barraRicerca.showsCancelButton = NO; }

Alla riga 15 abbiamo inizializzato il nuovo array, che ci servirà nell’algoritmo di ricerca. Inizialmente questa lista coinciderà con quella degli elementi iniziali, mentre poi verrà modificata mentre l’utente inserisce la stringa di ricerca. Nelle righe 20, 22 e 24 abbiamo definito dei comportamenti per il nostro box di ricerca, come potete capire dai commenti. Il secondo metodo da modificare è “numberOfRowsInSection”. Ecco il nuovo codice:

Guida pratica a!’iPhone SDK"

62


1 //setta il numero di righe della tabella 2 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ 3 ! //il numero di righe deve corrispondere al numero di elementi della lista 4 ! return [filteredListContent count]; 5 }

Questa modifica va eseguita in quanto la tabella ora non è più composta dagli elementi della lista originale, ma da quelli della lista filtrata, ovvero di quegli elementi selezionati mediante la ricerca. Ovviamente se l’utente non esegue nessuna ricerca, gli elementi della lista filtrata corrisponderanno agli elementi della lista originale. Se vi è chiaro questo ragionamento, è facile intuire quali saranno i prossimi metodi da modificare: il primo è “cellForRowAtIndexPath:”, ovvero il metodo che si occupa di inserire i valori nelle celle. Modificate l’ultima istruzione al suo interno nella seguente maniera: 1 //inseriamo nella cella l'elemento della lista corrispondente 2 cell.textLabel.text = [filteredListContent objectAtIndex:indexPath.row];

Modifichiamo, poi, il metodo “commitEditingStyle” modificando l’istruzione presente alla riga 4: 1 2 3 4 5 6

/! //controlla se l'azione compiuta è un'eliminazione ! if (editingStyle == UITableViewCellEditingStyleDelete) { ! ! //elimina l'elemento dalla lista ! ! [filteredListContent removeObjectAtIndex:indexPath.row]; ! ! //elimina le'elemento dalla tabella ! ! [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 7 ! ! 8 ! }

L’ultimo metodo da modificare, infine, è “didSelectRowAtIndexPath:” e anche in questo caso l’unica modifica riguarda proprio la lista di riferimento. 1 // Se selezioniamo una riga appare un pop-up con l'elemento in questione 2 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 3 ! UIAlertView *popUp = [[UIAlertView alloc] initWithTitle:@"Hai selezionato:" message:[filteredListContent objectAtIndex:indexPath.row] delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil]; 4 ! [popUp show]; 5 ! [popUp release]; 6 }

Abbiamo così eseguito tutte le modifiche necessarie!

Guida pratica a!’iPhone SDK"

63


I MPLEMENTIAMO

LA RICERCA

È arrivato il momento di implementare la ricerca vera e propria. Prima di mostrarvi i passaggi necessari, devo premettere che il codice non è stato scritto da me, ma l’ho preso da un esempio realizzato dalla stessa Apple. I commenti, quindi, saranno davvero pochi, anche perché non è fondamentale capire come funziona tale algoritmo, in quanto lo stesso codice si può utilizzare in qualsiasi altra applicazione che necessiti di una ricerca. Iniziamo con due metodi “accessori”, ovvero non legati direttamente all’algoritmo di ricerca. Ecco i due metodi da inserire nel file “RootViewController.m”: 1 // metodo chiamato quando l'utente inizia ad inserire la chiave di ricerca 2 - (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar{ 3 ! // visualizza il bottone per uscire dalla ricerca 4 ! barraRicerca.showsCancelButton = YES; 5 ! // disattiviamo la possibilità di modificare le celle della tabella 6 ! self.navigationItem.rightBarButtonItem.enabled = FALSE; 7 } 8 // metodo richiamato quando l'utente ha terminato la ricerca 9 - (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar{ 10 ! // nascondiamo il bottone "Cancel" del box di ricerca 11 ! barraRicerca.showsCancelButton = NO; 12 }

Il primo metodo viene richiamato quando l’utente inizia ad inserire la chiave di ricerca: mostriamo il bottone per annullare la ricerca e disattiviamo il bottone per modificare le celle (questo per non creare strani comportamenti). Il secondo metodo, invece, viene richiamato quando la ricerca è terminata. Eccovi altri due metodi da aggiungere:

Guida pratica a!’iPhone SDK"

64


1 // metodo richiamato quando il bottone "Cancel" viene premuto 2 - (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar{ 3 ! /* se l'utente esegue una ricerca valida, ma poi la annulla ! dobbiamo inserire i valori originali nella tabella*/ 4 ! if (barraRicerca.text.length > 0){ 5 ! ! [filteredListContent removeAllObjects]; 6 ! ! [filteredListContent addObjectsFromArray: lista]; 7 ! } 8 ! // ricarichiamo la tabella 9 ! [self.tableView reloadData]; 10 ! [barraRicerca resignFirstResponder]; 11 ! //azzeriamo il box di ricerca 12 ! barraRicerca.text = @""; 13 ! //riabilitiamo il tasto per la modifica della tabella 14 ! self.navigationItem.rightBarButtonItem.enabled = TRUE; 15 } 16 17 // metodo richiamato quando il bottone "Done" viene premuto 18 - (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar{ 19 ! // se il box di ricerca è vuoto abilitiamo la modifica della tabella 20 ! if ([filteredListContent count] == [lista count]) 21 ! ! self.navigationItem.rightBarButtonItem.enabled = TRUE; 22 ! else 23 ! ! self.navigationItem.rightBarButtonItem.enabled = FALSE; 24 ! [barraRicerca resignFirstResponder]; 25 }

Il primo metodo viene richiamato alla pressione del tasto “Cancel” che appare quando l’utente inizia ad inserire la sua chiave di ricerca. Questo metodo dovrà ripristinare la tabella al suo stato originale, ovvero con gli elementi della lista di partenza, e settando in maniera corretta tutte le caratteristiche desiderate. Discorso simile vale per il secondo metodo, che viene richiamato quando si preme “Done” sulla tastiera virtuale. I commenti presenti nei due metodi dovrebbero rendere tutte le istruzioni comprensibili. Quello che manca ora è l’algoritmo di ricerca vero e proprio, che è il seguente:

Guida pratica a!’iPhone SDK"

65


1 // algoritmo di ricerca 2 - (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText{ 3 ! // azzeriamo la lista con gli elementi filtrati 4 ! [filteredListContent removeAllObjects]; 5 ! // search the table content for cell titles that match "searchText" 6 ! // if found add to the mutable array and force the table to reload 7 ! NSString *cellTitle; 8 ! for (cellTitle in lista){ 9 ! ! NSComparisonResult result = [cellTitle compare:searchText options:NSCaseInsensitiveSearch range:NSMakeRange(0, [searchText length])]; 10 ! ! if (result == NSOrderedSame){ 11 ! ! ! [filteredListContent addObject:cellTitle]; 12 ! ! } 13 ! } 14 ! [self.tableView reloadData]; 15 }

Per questo algoritmo non voglio spendere parole, in quanto, come detto in precedenza, è stato scritto da Apple, quindi non posso permettermi di fare modifiche! Cliccate ora su “Build and Go!”, se avete eseguito tutto correttamente si aprirà la vostra applicazione!

Guida pratica a!’iPhone SDK"

66


Capitolo 10: gestiamo più viste (file “.xib” multipli) In questo capitolo vedremo un’aspetto fondamentale di un’applicazione, ovvero al gestione di più viste. Questa gestione riguarderà varie viste creare con Interface Builder (e quindi diversi file “.xib”), in quanto è l’approccio più semplice e anche più personalizzabile. L’applicazione che andremo a realizzare sarà davvero molto semplice, però è importante seguire bene tutti i passaggi, in modo che possiate replicare la stessa struttura anche nelle vostre applicazioni più complesse.

D EFINIAMO

LA STRUT TURA DEL PROGET TO

Iniziamo, come sempre, creando un nuovo progetto di tipo "View-Based Application" e chiamiamolo "MultiViewApp". Inseriamo subito una nuova vista. Per fare ciò, andiamo in "File -> New File..." e da "User Interface" scegliamo "View XIB", chiamandola "vistaDue".

Dobbiamo, inoltre, creare anche la classe che dovrà essere associata a tale vista. Andiamo in "File -> New File..." e da "Cocoa Touch Class" scegliamo "UIViewController subclass". Chiamiamo tale classe "VistaDueController". Se abbiamo eseguito tutto correttamente dovreste avere una struttura del vostro progetto così:

Guida pratica a!’iPhone SDK"

67


Abbiamo così un progetto composto da due viste: “MultiViewAppViewController” (che è stata creata di default da XCode) e “VistaDue”, che abbiamo appena creato.

D EFINIAMO

LA PRIMA VISTA

Apriamo il file "MultiViewAppController.h" e inseriamo la seguente dichiarazione: 1 2 3 4 5 6 7 8 9 10

#import <UIKit/UIKit.h> #import "VistaDueController.h" @interface MultiViewAppViewController : UIViewController { } -(IBAction)cambiaVista; @end

Come vedete alla riga 8 abbiamo definito un’azione, che andremo poi a collegare ad un pulsante. Non dimenticatevi di importare la classe “VistaDueController”, come fatto alla riga 2. Salviamo il file appena modificato e apriamo “MultiViewAppViewController.xib”. Dobbiamo inserire al suo interno un tasto, che ci permetterà di passare alla vista successiva. Inserite un tasto come questo (oppure un altro a piacere):

Guida pratica a!’iPhone SDK"

68


Ora dobbiamo collegarci l’azione che abbiamo appena definito. Dal Pannello dei Documenti selezioniamo il “File’s Owner” e andiamo nel “Connections Inspector”. Colleghiamo l’azione “cambiaVista” con il bottone, selezionando “Touch Up Inside” quando apparirà il menù a tendina. Ecco come deve presentarsi poi il vostro pannello:

Possiamo salvare il file e chiudere Interface Builder.

D EFINIAMO

LA SECONDA VISTA

Dobbiamo ora definire gli elementi della seconda vista. Questa volta è un po’ più complicato, in quanto andremo a definire un protocollo, che poi verrà implementato dalla classe “MultiViewAppController”. Ecco cosa dovete scrivere nel file “VistaDueController.h”:

Guida pratica a!’iPhone SDK"

69


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

#import <UIKit/UIKit.h> @protocol VistaDueControllerDelegate; @interface VistaDueController : UIViewController { ! id <VistaDueControllerDelegate> delegate; } @property (nonatomic, assign) id <VistaDueControllerDelegate> delegate; - (IBAction)termina; @end @protocol VistaDueControllerDelegate - (void)fineCambioVista:(VistaDueController *)controller; @end

Fino alla riga 13 non dovreste vedere niente di strano, si tratta di una semplice classe in cui viene definito un elemento “delegate” alla riga 6 (è vero, è un po’ strana la definizione, ma niente di particolare)e un’azione alla riga 11 (che ci permetterà di chiudere questa vista). La novità arriva dalla riga 15 in poi, in quanto definiamo il metodo “fineCambioVista”, che dovrà essere implementato poi dalla classe “MultiViewAppController”. Salviamo il file appena modificato e apriamo “VistaDue.xib”, che dovete impostare nel seguente modo (sulla falsariga della vista precedente):

Guida pratica a!’iPhone SDK"

70


Dal Pannello dei Documenti andiamo nel “File’s Owner”. Dobbiamo per prima cosa associare la classe a questa vista. Andiamo nell’Identity Inspector e nel campo “Class” scegliamo “VistaDueController”:

Spostiamoci, poi, nel “Connecions Inspector”, in cui andremo a collegare l’azione “termina” con il bottone che abbiamo inserito nella vista. Colleghiamo, inoltre, l’elemento “view” con la vista, altrimenti l’applicazione crasherà appena cercherete di entrare in questa vista. Ecco come si presenta il pannello dopo questi collegamenti:

Abbiamo terminato anche questa vista, possiamo salvare e chiudere Interface Builder.

S CRIVIAMO

IL CODICE NECE SSARIO

Prima di iniziare a inserire il codice nelle varie classi, modificate l’intestazione nel file “MultiViewAppViewController.h”: 1 @interface MultiViewAppViewController : UIViewController <VistaDue2 ControllerDelegate> {

Come potete notare abbiamo inserito il protocollo “VistaDueControllerDelegate”, che abbiamo definito in precedenza. Iniziamo a completare l’implementazione della classe relativa alla prima vista. Apriamo il file “MultiViewAppViewController.m” e inseriamo il seguente codice:

Guida pratica a!’iPhone SDK"

71


1 2 3 4 5 6 7 8 9

#import "MultiViewAppViewController.h" @implementation MultiViewAppViewController -(IBAction)cambiaVista{ ! VistaDueController *controller = [[VistaDueController alloc] initWithNibName:@"VistaDue" bundle:nil]; ! controller.delegate = self; ! ! controller.modalTransitionStyle = UIModalTransitionStyleCoverVertical; ! [self presentModalViewController:controller animated:YES]; ! ! [controller release]; }

10 11 12 13 14 15 - (void)fineCambioVista:(VistaDueController *)controller { 16 [self dismissModalViewControllerAnimated:YES]; 17 }

Alla riga 5 inizia la definizione del metodo “cambiaVista”, che permette di caricare la seconda vista. Alla riga 6, infatti, viene proprio definito un oggetto relativo alla VistaDue: notate che a “initWithNibName:” dobbiamo passare il nome del file xib che vogliamo caricare. La riga 8 è quella che definisce il tipo di animazione nel passaggio da una vista all’altra. Eccovene alcune, scegliete quella che vi piace di più: • UIModalTransitionStyleCoverVertical, la nuova vista appare dal basso verso l’alto; • UIModalTransitionStyleCrossDissolve, la nuova vista appare in dissolvenza; • UIModalTransitionStyleFlipHorizontal, la nuova vista appare con una ruotazione della prima. L’istruzione alla riga 10, infine, è quella che effettua il vero e proprio cambio di vista. Come potete vedere non è niente di complicato, anche perchè le istruzioni da utilizzare sono sempre queste. Alla ria 15 abbiamo implementato il metodo che abbiamo definito con il protocollo “VistaDueDelegate”. Questo metodo permetterà di tornare alla prima vista quando uscite dalla seconda. Ci manca solo un metodo da inserire nel file “VistaDueController.m”. Ecco cosa dovete inserire: 1 2 3 4 5

@synthesize delegate; - (IBAction)termina { ! [self.delegate fineCambioVista:self];! }

Questo metodo viene richiamato quando vogliamo tornare alla prima vista.

Guida pratica a!’iPhone SDK"

72


Facciamo clic su “Build and Go!” e testiamo la nostra applicazione funzionante!

Guida pratica a!’iPhone SDK"

73


Capitolo 11: Come creare una TabBar Application Uno dei componenti più utilizzati (e uno dei più apprezzati dagli utenti finali) sono le TabBar, che avete già conosciuto nel capitolo 2. In questo tutorial vedremo come creare una struttura di base, inserendo due viste generiche e una più particolare e utile: una tabella integrata ad una NavigationBar, che ci permetterà di navigare nei sottolivelli della tabella (per capirci, la struttura che è presente nell’applicazione nativa iPod).

P ARTE 1:

LA STRUT TURA DI BASE

Abbiamo già descritto cosa faremo in questa prima parte: realizzeremo la struttura di base, che ci permetterà di inserire diverse viste nella tab. È importante seguire bene tutti i passaggi per non ritrovarsi con errori strani, che spesso portano a perdere tempo e possono essere facilmente evitati.

C REIAMO

UNA

T AB B AR “ PULITA ”

Iniziamo creando un nuovo progetto di tipo “Tab Bar Application” e chiamandolo “TabBarTutorial”. Vogliamo andare a definire una struttura di base pulita, personalizzandola poi a nostro piacimento. Eliminiamo, quindi, alcuni componenti che XCode ha già creato per noi, ma che non vogliamo sfruttare: cancelliamo il file “SecondView.xib”, “FirstViewController.h” e “FirstViewController.m”. Possiamo ora fare doppio clic su “MainWindow.xib”, si aprirà Interface Builder che ci mostrerà questo layout per la nostra applicazione:

Guida pratica a!’iPhone SDK"

74


Selezioniamo ognuno dei tab ed eliminiamolo, ottenendo questa struttura:

Salviamo questo file e chiudiamo pure Interface Builder.

D EFINIAMO

LE DUE VISTE

Dobbiamo ora definire le due viste che dovremo inserire nella nostra applicazione. Dal menù “File” scegliamo “New File…” e selezioniamo “Empty XIB”. Creiamo due di questi file chiamandoli, rispettivamente, “PrimaVista” e “SecondaVista”.

Guida pratica a!’iPhone SDK"

75


Nella cartella “Resources” del nostro progetto vedremo i due file appena creati:

Dobbiamo ora creare anche le due classi che gestiranno le due viste: nel tutorial non serviranno a niente, ma voglio implementarle in modo da darvi già una struttura che potrete utilizzare nelle vostre applicazioni. Andiamo, quindi, in “File -> New File…” e spostiamoci nella sezione “Cocoa Touch Class”, in cui selezioniamo il modello “UIViewController”: anche in questo caso dobbiamo creare due classi, chiamate “PrimaVistaController” e “SecondaVistaController”.

Possiamo spostare i file appena creati nella sezione “Classes” del nostro progetto. Abbiamo così definito tutti i componenti necessari, non ci resta che definire la struttura grafica delle due viste.

C REIAMO L ’ ASPET TO

GRAFICO DELLE DUE VISTE

Clicchiamo su “PrimaVista.xib” per aprirla in Interface Builder. Dalla Libreria, inseriamo una “UIView” all’interno del Pannello dei Documenti (”Tools -> Reveal in Document Window”).

Guida pratica a!’iPhone SDK"

76


Apriamo la vista appena inserita e modifichiamone l’aspetto a nostro piacimento (io per semplicità inserirò solo due label, in questo tutorial non ci servirà altro). Dall’”Attributes Inspector” selezioniamo “Tab Bar” dal sotto-menù a tendina “Bottom Bar”:

Questa proprietà non ha nessun fine pratico, però ci consente di aver una visione completa della nostra vista, tenendo in considerazione anche la tab bar (in questo modo saprete esattamente quanto spazio avete a disposizione per i vostri componenti). Ecco come si presenta la nostra vista:

Guida pratica a!’iPhone SDK"

77


Ora dobbiamo collegare questa vista con la classe che abbiamo definito in precedenza. Sempre dal Pannello dei Documenti selezioniamo il “File’s Owner”:

In “Identity Inspector” selezioniamo “PrimaVistaController” dal menù a tendina “Class”.

Guida pratica a!’iPhone SDK"

78


Andiamo poi in “Connections Inspector” e colleghiamo l’elemento “view” con la vista che abbiamo appena creato. Se abbiamo eseguito il passaggio in maniera corretta avremo questo risultato:

Abbiamo così completato la definizione della vista. Eseguiamo lo stesso procedimento anche per il file “SecondaVista.xib”, collegandola però alla classe “SecondaVistaController”. Possiamo poi salvare tutto e chiudere Interface Builder.

I MP OSTIAMO

LA

T AB B AR

Ora è giunto il momento di impostare la struttura vera e propria della nostra Tab Bar. Apriamo il file “MainWindow.xib” Dalla Libreria inseriamo due componenti UIViewController trascinandoli nella “Tab Bar” posta a fondo vista:

Guida pratica a!’iPhone SDK"

79


Il risultato finale sarĂ il seguente:

Iniziamo facendo doppio clic sul primo elemento, facendo attenzione che si evidenzi in questo modo:

Guida pratica a!â&#x20AC;&#x2122;iPhone SDK"

80


Nel pannello “Attributes Inspector”, selezioniamo “PrimaVista” dal menù “NIB Name”:

Ora facciamo doppio clic sul nome del tab (che per default è “Item”), e rinominiamolo a nostro piacere. Ripetiamo, poi, lo stesso procedimento con il secondo tab, associano questa volta la “SecondaVista”. Se avete eseguito tutto in maniera corretta avrete il seguente risultato:

Guida pratica a!’iPhone SDK"

81


Chiudiamo ora Interface Builder, salvando tutti i file. Da XCode clicchiamo su “Build and Go!” e testiamo se tutto funziona in maniera corretta!

P ARTE 2: I NSERIAMO

UNA

N AVIGATION B AR

Nella seconda parte di questo tutorial analizzeremo l’aspetto più importante e più delicato, ovvero l’implementazione di una UINavigationBar e di una tabella. Questa combinazione ci permetterà di navigare nei sotto-elementi della tabella. Ovvero, quando l’utente seleziona una determinata cella si aprirà una corrispondente vista che avremo definito con Interface Builder. La navigation bar, poi, ci permetterà di tornare alla tabella principale. Un po’ come avviene nel menù “Impostazioni” del’iPhone / iPod Touch!

C REIAMO

UN NUOVO ELEMENTO PER LA

T AB B AR

Iniziamo creando la classe che gestirà la nuova vista. Dal menù “File” scegliamo “New File…”, nel pannello che apparirà selezioniamo “UIViewController subclass” e spuntiamo la voce “UITableViewController subclass” presente nelle opzioni. Chiamiamo questa nuova classe “TabellaController”. Abbiamo già imparato a gestire una tabella nel capitolo 9, quindi non rispiegherò il codice utilizzato. Riutilizziamo gli stessi metodi, quindi inserite nel file “TabellaController.h” il seguente codice:

Guida pratica a!’iPhone SDK"

82


1 #import <UIKit/UIKit.h> 2 3 @interface TabellaController : UITableViewController {! 4 ! //array che conterrà gli elementi da visualizzare nella tabella ! NSArray *lista; 5 } 6 7 @property (nonatomic, retain) NSArray *lista; 8 9 @end

Mentre in “TabellaController.m” inserite questi metodi: 1 2 3 4 5 6 7 8

#import "TabellaController.h" @implementation TabellaController @synthesize lista;

- (void)awakeFromNib{! ! // creiamo la lista e inseriamo una serie di elementi da visualizzare nella nostra tabella 9 ! lista = [[NSArray alloc] initWithObjects:! @"iPhone", @"iPod", @"iPod Touch", @"iMac", @"iBook", @"MacBook", @"MacBook Pro", @"Mac Pro", @"PowerBook", nil]; 10 } 11 12 //setta il numero di sezioni della tabella 13 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{ 14 ! return 1; 15 } 16 17 //setta il numero di righe della tabella 18 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ 19 ! //numero di righe deve corrispondere al numero di elementi della 20 lista 21 ! return [lista count]; }

Guida pratica a!’iPhone SDK"

83


22 //settiamo il contenuto delle varie celle 23 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ 24 ! 25 ! UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cellID"]; 26 ! 27 ! if (cell == nil){ 28 ! ! cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:@"cellID"] autorelease]; 29 ! ! 30 ! } 31 ! //inseriamo nella cello l'elemento della lista corrispondente 32 ! cell.textLabel.text = [lista objectAtIndex:indexPath.row]; 33 ! 34 ! return cell; 35 }

Salviamo entrambi i file e riapriamo “MainWindow.xib” per tornare in Interface Builder.

D EFINIAMO L ’ ASPET TO

DEL NUOVO ELEMENTO

Dalla Libreria prendiamo un componente UINavigationController e inseriamolo nella tab bar, proprio come abbiamo nella prima parte di questo tutorial.

Guida pratica a!’iPhone SDK"

84


Proprio come abbiamo fatto in precedenza cambiamo il nome della scheda in “Tabella”. Ecco il risultato finale:

Ora non ci resta che inserire la tabella all’interno di questa vista. Dalla Libreria prediamo un componente UITableViewController e inseriamolo nella nostra vista. Il risultato che dovete ottenere è il seguente:

Guida pratica a!’iPhone SDK"

85


Ora dobbiamo solo collegare la classe alla tabella appena inserita. Dal Pannello dei Documenti (”Tools -> Reveal in Document Window”) navighiamo fino al seguente percorso:

Come mostrato in figura, selezioniamo il componente “Table View Controller” (che non è altro che la nostra tabella) e apriamo l’”Identity Inspector”. Dal menù Class scegliamo “TabellaController”:

Abbiamo così concluso con la creazione della nostra tabella. Salviamo tutto, torniamo in XCode e clicchiamo su “Build and Go!”: la tabella sarà ora presente e funzionante nell’applicazione!

Guida pratica a!’iPhone SDK"

86


I MPLEMENTIAMO

DUE VISTE DI DET TAGLIO

Ora vediamo di analizzare un aspetto che molti utenti mi hanno chiesto via mail. Se noi volessimo associare un determinato file “xib” (ovvero creato con Interface Builder) ad una cella, come potremmo fare? In questa seconda parte del tutorial vedremo proprio di analizzare i passaggi necessari. Andremo a definire due viste, una che conterrà una foto dell’elemento “iPhone”, mentre un’altra che avviserà l’utente dell’assenza di informazioni per un determinato prodotto. Ovviamente potreste realizzare una vista con i dettagli per ogni prodotto presente nella tabella, ma il meccanismo rimane invariato. Iniziamo creando due nuovi file xib, dal menù “File -> New File…” e scegliendo “Empty XIB”. Io ho chiamato il primo file “iPhoneDetail” e il secondo “OtherDetail”, ma nulla vieta di chiamarli in modo diverso!

Guida pratica a!’iPhone SDK"

87


Procediamo proprio come abbiamo fatto all’inizio dello scorso tutorial per le viste “PrimaVista” e “Seconda Vista”, quindi definiamo subito via codice le due classi necessarie. Andiamo, quindi, in “File -> New File…” e spostiamoci nella sezione “Cocoa Touch Class”, in cui selezioniamo il modello “UIViewController”: anche in questo caso dobbiamo creare due classi, chiamate “iPhoneDetailController” e “OtheDetailController”.

Possiamo spostare i file appena creati nella sezione “Classes” del nostro progetto. Ora siamo pronti per definire l’aspetto di queste due nuove viste.

D EFINIAMO L ’ ASPET TO

DELLE DUE VISTE DI DET TAGLIO

Apriamo il file “iPhoneDetail.xib” in Interface Builder. Il procedimento è, come già detto, uguale a quello svolto per la definizione delle due viste “PrimaVista” e “SecondaVista”. Inseriamo, quindi, un componente UIView nel Pannello dei Documenti e modifichiamolo a nostro piacimento. Io ho inserito una foto di un iPhone, ovviamente voi potrete inserire quello che volete. Ecco come risulta essere la mia vista:

Guida pratica a!’iPhone SDK"

88


Ora associamo questa vista alla sua classe. Dal Pannello dei Documenti selezioniamo il “File’s Owner” e nell’”Identity Inspector” selezioniamo “iPhoneDetailController” come classe:

Andiamo poi in “Connections Inspector” e colleghiamo l’elemento “view” con la vista che abbiamo appena creato (quella contenente le due label per intenderci). Se abbiamo eseguito il passaggio in maniera corretta avremo questo risultato:

Guida pratica a!’iPhone SDK"

89


Abbiamo così completato la definizione della vista. Eseguiamo lo stesso procedimento anche per il file “OtherDetail.xib”, collegandola però alla classe “OtherDetailController”. Ecco come appare tale vista:

Possiamo salvare tutto e chiudere Interface Builder.

Guida pratica a!’iPhone SDK"

90


C OME

RICHIAMARE LE DUE VISTE VIA CODICE

Ora non ci resta che analizzare il codice che ci permette di aprire queste due viste. Apriamo il file “TabellaController.h” e modifichiamolo nella seguente maniera: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

#import <UIKit/UIKit.h> #import "iPhoneDetailController.h" #import "OtherDetailController.h" @interface TabellaController : UITableViewController {! ! //array che conterrà gli elementi da visualizzare nella tabella ! NSArray *lista; ! ! }

//controller della vista che dovrà essere aperta UIViewController *detail;

@property (nonatomic, retain) NSArray *lista; @end

Abbiamo per prima cosa importato le due classi delle viste (righe 2 e 3), e poi definito una vista generica (riga 10), che poi inizializzeremo con la classe “iPhoneDetailController” oppure “OtherDetailController”, a seconda del caso. Perché abbiamo utilizzato “UIViewController” come tipo dell’elemento “detail”? Perchè abbiamo sfruttato un paradigma della programmazione ad oggetti, che ci permette di definire un elemento con una superclasse, per poi inizializzarlo con una sottoclasse più specifica. Ora apriamo il file “TabellaController.m” e inseriamo il metodo che viene richiamato quando si clicca su una cella:

Guida pratica a!’iPhone SDK"

91


1 // Metodo relativo alla selezione di una cella 2 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 3 ! 4 ! if (indexPath.row == 0){ 5 ! ! //l'utente ha cliccato sull'elemento iPhone, quindi carichiamo la vista relativa 6 ! ! detail = [[iPhoneDetailController alloc] initWithNibName:@"iPhoneDetail" bundle:[NSBundle mainBundle]]; 7 ! } else { 8 ! ! detail = [[OtherDetailController alloc] initWithNibName:@"OtherDetail" bundle:[NSBundle mainBundle]]; 9 ! } 10 ! 11 ! //Facciamo visualizzare la vista con i dettagli 12 ! [self.navigationController pushViewController:detail 13 animated:YES]; 14 ! //rilasciamo il controller 15 ! [detail release]; 16 ! 17 ! detail = nil; }

Anche questo metodo lo avevamo già trovato nel tutorial dedicato alle tabelle. Analizziamo, però, il codice al suo interno. Troviamo inizialmente un controllo if (riga 4), che controlla se l’utente ha selezionato al prima cella, ovvero quella contenente l’elemento iPhone: se il controllo da esito positivo, inizializziamo l’elemento “detail” con la classe relativa alla vista “iPhoneDetail” (riga 6), altrimenti con l’altra vista generica (riga 8). La clausola “initWithNibName” si riferisce proprio al file xib che deve essere associato all’elemento “detail”. Dopo il ciclo troviamo le istruzioni che ci permettono di far apparire la nuova vista; non preoccupatevi troppo, sono sempre queste istruzioni da utilizzare. Abbiamo concluso!! Clicchiamo su “Build and Go!” e godiamoci la nostra applicazione funzionante!!

Guida pratica a!’iPhone SDK"

92


Guida pratica a!â&#x20AC;&#x2122;iPhone SDK"

93


Capitolo 12: XML Dopo aver visto molti componenti, in questo capitolo vedremo come integrare una tecnologia molto utilizzata, specialmente in ambito web: stiamo parlando di XML. Vedremo, quindi, come leggere un file XML, da cui ricaveremo delle informazioni che abbiamo salvato. Questa operazione verrà eseguita in locale (ovvero il file xml sarà all’interno del nostro progetto), ma nulla vieta di avere il file caricato su un server web da cui accediamo tramite la nostra applicazione.

C OSA È XML? XML è un metalinguaggio (in quanto non è un linguaggio di programmazione vero e proprio) di markup, ovvero un linguaggio che consente di estendere o controllare il comportamento di altri linguaggi. Il linguaggio di markup più famoso è sicuramente l’HTML, che ha molte analogie con l’XML. XML è l’acronimo di eXtensible Markup Language, da cui possiamo capire la caratteristica fondamentale di questo linguaggio: ci permette di creare tag personalizzati, in base alle proprie esigenze. Sarà più semplice comprendere come funziona questo linguaggio mediante un esempio:

La prima riga definisce la versione di XML in uso e la codifica utilizzata (secondo le norme ISO). Dalla seconda riga in poi, invece, troviamo dei tag personalizzati, che vanno a modellare dei dati a nostro piacimento. Possiamo vedere come abbiamo definito un tag generale “studenti”, che viene iniziato alla seconda riga e concluso all’ultima. Nel mezzo troviamo, invece, altri tag, che riportano le informazioni che vogliamo memorizzare, per poi utilizzarle a nostro piacimento. Ci sono alcune piccole regole da rispettare nella struttura XML:

Guida pratica a!’iPhone SDK"

94


1. I tag non possono iniziare con numeri o caratteri speciali e non possono contenere spazi. Corretti: <nome>, <cognome>, <dataDiNascita> Errati: <&soldi>, <12peso>, <anno di nascita> 2. I tag devono essere bilanciati (ogni tag aperto deve essere chiuso) Corretto: <nome>Andrea</nome> Errato: <nome>Andrea 3. I tag non devono contenere errori di annidamento. Ecco alcuni esempi errati:

4. Si possono inserire degli attributi all’interno dei tag; la struttura sarà quindi la seguente: <nometag attributo1=”valore1ʺ″ attributo2=”valore2ʺ″> Valore </nometag> I nostri elementi, quindi, potranno essere scritti anche nella seguente maniera:

Questa struttura è del tutto uguale a quella precedente. Notate che in questo caso non abbiamo usato il tag di chiusura, ma abbiamo inserito “/” all’interno del tag stesso proprio per indicare che quel tag non ha elemento di chiusura. Quello che cambierà sarà solamente il modo di leggere i valori via codice.

Guida pratica a!’iPhone SDK"

95


XML

NEL

SDK

DI I P HONE

Per ora abbiamo fatto una panoramica su XML in generale, presentando gli aspetti fondamentali di tale linguaggio. Ma come possiamo integrarlo con le nostre applicazioni?L’oggetto che si occupa di recuperare i dati da un file XML viene detto parser. Esistono vari tipi di parser (diversi per linguaggi e tecnologie), noi andremo ad utilizzare SAX. La caratteristica di questo parser sta nel fatto che processa i documenti linea per linea: dati a cui si è acceduto in precedenza non possono essere riletti senza la rielaborazione dell’intero documento. Può essere uno svantaggio, ma è l’unico parser disponibile nel SDK per iPhone!!

C REIAMO

LA STRUT TURA GRAFICA

Iniziamo ora a creare la nostra applicazione. Creiamo un nuovo progetto di tipo “View-Based Application” e chiamiamolo “xmlTutorial”. Prima di definire l’aspetto grafico, però, dichiariamo i componenti che ci servono. Apriamo il file “xmlTutorialViewController.h” e modificatelo così: 1 2 3 4 5 6 7 8 9 10 11

#import <UIKit/UIKit.h> @interface xmlTutorialViewController : UIViewController { ! IBOutlet UITextView *textArea; ! ! NSString *path; } -(IBAction)avviaParsing; @end

Abbiamo dichiarato una TextView in cui inseriremo i dati letti dal file xml, un’azione, che andrà collegata ad un bottone (tale azione farà iniziare il processo di parsing) e una stringa che conterrà il percorso del file xml. Possiamo salvare il file e dedicarci alla struttura grafica dell’applicazione. Apriamo ora il file “xmlTutorialViewControlle.xib”, che avvierà Interface Builder. Nella nostra applicazione, inseriamo un bottone e una TextView, di dimensioni abbastanza ampie, in quanto dovrà contenere tutti i valori letti dal file xml. Dovreste ottenere un risultato come questo:

Guida pratica a!’iPhone SDK"

96


Ora, selezionando la UITextView, entriamo in “Attributes Inspector” e togliamo la spunta a “Editable”:

questo perché non vogliamo che l’utente possa modificare i valori presenti nella TextView (ovvero deve essere di sola lettura). Dal pannello dei documenti (”Tools -> Reveal in Document Window”) selezioniamo “File’s Owner”, ovvero la classe che gestisce il nostro file.

Guida pratica a!’iPhone SDK"

97


Apriamo il “Connections Inspector” e potremo vedere alcuni elementi, più i due che abbiamo definito noi all’inizio del nostro progetto. Colleghiamo “textArea” con la UITextView presente nella nostra vista, e l’azione “avviaParsing” con il bottone: quando apparirà il menù con tutte le azioni disponibili, scegliamo “Touch Up Inside”. Se avrete eseguito tutto correttamente avrete un pannello che si presenterà così:

Abbiamo terminato la creazione della struttura grafica. Possiamo salvare tutto e chiudere Interface Builder.

S CRIVIAMO

IL CODICE NECE SSARIO

Prima di procedere con il codice necessario, dobbiamo inserire all’interno del progetto il file xml con i nostri dati. Trascinate il file xml (che potete creare ex-novo, oppure creare copiando il codice presentato nella prima parte di questo tutorial tutorial) all’interno della cartella “Resources” del nostro progetto, spuntando l’opzione per copiarlo nella cartella fisica del progetto:

Guida pratica a!’iPhone SDK"

98


Apriamo ora il file “xmlTutorialViewController.m” e definiamo il seguente metodo: 1 2 3 4 5 6

// Metodo eseguito all'avvio della vista - (void)viewDidLoad { [super viewDidLoad]; ! // definiamo il percorso del file xml ! NSString *pathProgetto = [[NSBundle mainBundle] bundlePath]; ! path = [[NSString alloc] initWithString:[pathProgetto stringByAppendingPathComponent:@"dati.xml"]]; 7 }

Questo metodo viene eseguito all’avvio della vista, e ci permette di definire dei comportamenti che devono essere eseguiti prima di ogni altra cosa. Con le due istruzioni che abbiamo inserito definiamo il percorso del nostro file “dati.xml”: esso viene cercato all’interno della cartella del nostro progetto. Queste istruzioni sono molto importanti, in quanto non viene definito un percorso assoluto (soluzione sempre sconsigliabile e spesso errata), ma viene definito il percorso effettivo in cui si trova il file. Dobbiamo ora definire l’azione che viene eseguita quando premiamo sul pulsante. Ecco il codice da inserire:

Guida pratica a!’iPhone SDK"

99


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18

-(IBAction)avviaParsing{ ! //Bisogna convertire il file in una NSURL altrimenti non funziona ! NSURL *xmlURL = [NSURL fileURLWithPath:path]; ! // Creiamo il parser ! NSXMLParser *parser = [[ NSXMLParser alloc] initWithContentsOfURL:xmlURL]; ! // Il delegato del parser e' la classe stessa (self) ! [parser setDelegate:self]; ! //Effettuiamo il parser ! BOOL success = [parser parse]; ! //controlliamo come è andata l'operazione ! if(success == YES){ ! ! //parsing corretto ! } else { ! ! //c'è stato qualche errore... ! } ! // Rilasciamo l'oggetto NSXMLParser ! [parser release]; }

Le istruzioni alle righe 3 e 5 ci permettono di definire il parser, partendo dal percorso del nostro file. Alla riga 9 avviamo il processo di parsing, salvando il risultato in una variabile booleana: se essa vale YES la conversione si è conclusa senza errori (riga 12), altrimenti c’è stato un errore (che potrebbe essere dovuto ad errori nella struttura del file xml oppure ad errori di scrittura del codice). Come potete vedere non si tratta di codice complesso, sono poche istruzioni che dovrebbero risultarvi chiare. La parte che viene ora è quella che si occupa di leggere i dati dal file xml. Iniziamo inserendo questo metodo:

Guida pratica a!’iPhone SDK"

100


1 - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict { 2 ! 3 ! if ([elementName isEqualToString:@"studenti"]){ 4 ! ! [textArea setText:[[NSString alloc] initWithFormat:@"%@\nInizio studenti",textArea.text]]; 5 ! } 6 ! else if([elementName isEqualToString:@"studente"]){ 7 ! ! [textArea setText:[[NSString alloc] initWithFormat:@"%@\nNuovo studente",textArea.text]]; 8 ! } 9 ! else if([elementName isEqualToString:@"matricola"]) { 10 ! ! [textArea setText:[[NSString alloc] initWithFormat:@"%@\nMatricola: ",textArea.text]]; 11 ! } 12 ! else if([elementName isEqualToString:@"cognome"]) { 13 ! ! [textArea setText:[[NSString alloc] initWithFormat:@"%@\nCognome: ",textArea.text]]; 14 ! }! 15 ! else if([elementName isEqualToString:@"nome"]) { 16 ! ! [textArea setText:[[NSString alloc] initWithFormat:@"%@\nNome: ",textArea.text]]; 17 ! } 18 }

Come potete osservare, vi sono una serie di controlli if, che vanno a testare l’elemento corrente, per riconoscerlo e per scrivere una stringa adeguata nella textArea che abbiamo predisposto. Questo processo è possibile perché conosciamo a priori la struttura del file xml: questo è quasi sempre vero, in quanto sarebbe quasi impossibile leggere un file xml di cui non conosciamo la struttura interna. Il metodo viene, ovviamente, richiamato ogni volta che il parser incontra un nuovo elemento, cioè l’apertura di un tag. Per completare il nostro programma mancano solo due metodi: 1 - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string { 2 ! [textArea setText:[[NSString alloc] initWithFormat:@"%@%@",textArea.text,string]]; 3 } 4 5 - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName { 6 ! [textArea setText:[[NSString alloc] initWithFormat:@"%@\nFine elemento: %@",textArea.text,elementName]]; 7 }

Guida pratica a!’iPhone SDK"

101


Il primo viene richiamato quando il parser incontra un valore racchiuso tra due tag (l’informazione vera e propria). Nel nostro caso ci limitiamo a inserirla nella textArea, però potreste fare delle operazioni più o meno complesse sulle informazioni che leggete dal file. L’ultimo metodo, invece, viene richiamato quando il parser incontra un tag di chiusura. Anche in questo caso l’unica azione che faremo sarà quello di inserire una stringa nella textArea. Possiamo finalmente cliccare su “Build and Go!” e testare la nostra applicazione funzionante!

Guida pratica a!’iPhone SDK"

102


Capitolo 13: SQL Nel capitolo precedente abbiamo visto come leggere un file XML e fare il parsing dei dati contenuti al suo interno. Non esiste, però, solo quella possibilità per accedere ad un archivio di dati. La tecnologia di maggior successo è sicuramente SQL, che si basa su database relazionali. In questo capitolo vedremo come sfruttare SQLite per interfacciarci con un database presente in locale (quindi salvato all’interno del nostro progetto). Nulla vieta, però, che il database risieda su un server remoto, e che quindi la connessione avvenga tramite la rete. Creeremo, quindi, una tabella in cui andremo ad inserire i valori letti dal nostro database, dopo aver eseguito una query predefinita. Devo premettere, però, che non parlerò di SQL e database relazionali, che devono essere già conosciuti da chi affronta questo capitolo. È una scelta che potrebbe non piacere a molti di voi, però richiederebbe troppo tempo e una trattazione che non può essere fatta in un semplice tutorial. Detto ciò, è possibile seguire questa guida e concludere con successo l’applicazione, anche senza conoscere niente di SQL, ovviamente alcune caratteristiche e alcuni passaggi potrebbero risultare di difficile comprensione. In questa guida sentirete spesso parlare di SQLite, ma cosa è di preciso? SQLite è una libreria che implementa un DBMS SQL, permettendo di creare un database all’interno di un unico file. Esso è molto indicato per scopi come il nostro, ovvero la creazione di applicazioni per dispositivi mobili, che non possono permettersi di avere un DMBS dedicato per la gestione delle basi di dati. Ovviamente fornisce un supporto parziale all’SQL, in quanto manca di alcune caratteristiche avanzate, che però dubito possiate utilizzare all’interno di un’applicazione. SQLite, comunque, è molto veloce e leggero, perfetto quindi per applicazioni per iPhone.

D EFINIAMO

UN NUOVO PROGET TO

Iniziamo creando un nuovo progetto di tipo “Navigation-based Application” e chiamiamolo “sqlTutorial”. Abbiamo quindi creato un progetto che ci fornisce già l’implementazione di una tabella, che visualizzerà i dati letti dal nostro database. Dobbiamo, però, inserire altre due cose molto importanti: una classe che si occuperà di comunicare con il database, e la libreria che permette tale comunicazione. Iniziamo creando la classe che serirà ai nostri scopi. Andiamo in “File -> New File…” e creiamo una “Objective-C class”, chiamandola semplicemente “Data”:

Guida pratica a!’iPhone SDK"

103


Dobbiamo ora inserire nel nostro progetto la libreria (o framework) che si occupa del collegamento con il database sql. Clicchiamo con il tasto destro sulla cartella “Frameworks” all’interno del nostro progetto, poi andiamo in “Add -> Existing Frameworks…” e dall’elenco seguente che apparirà selezioniamo “libsqlite3.0.dylib”:

Guida pratica a!’iPhone SDK"

104


Abbiamo così terminato la definizione della struttura principale del nostro progetto. Se avete eseguito tutto in maniera corretta dovreste avere un progetto come questo:

D EFINIAMO

LA CLASSE

“D ATA ”

Dobbiamo ora implementare la classe “Data”, su cui si basa gran parte di questo capitolo. Prima di iniziare a scrivere codice, focalizziamo l’attenzione su ciò che deve fare questa classe. Essa avrà il compito di: • creare una connessione con il database (di cui noi specificheremo un indirizzo, in questo caso locale, ma nulla vieterebbe di avere un database in remoto); • interrogare la base di dati eseguendo una query impostata via codice; • inserire i risultati della query all’interno di un’array, che verrà poi visualizzato all’interno della tabella. Vediamo ora di implementare queste funzionalità, più altre caratteristiche che ci serviranno come supporto. Iniziamo aprendo il file “Data.h” e inserendo il seguente codice:

Guida pratica a!’iPhone SDK"

105


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

#import <Foundation/Foundation.h> #import <sqlite3.h> @interface Data : NSObject { ! // Lista contenente i dati letti dal database ! NSMutableArray *lista; } -

(id)init:(NSString *)pathDB; (void)caricaValoriDaDB:(NSString *)dbPath; (unsigned)getSize; (id)objectAtIndex:(unsigned)theIndex;

@property (nonatomic, retain) NSMutableArray *lista; @end

Alla riga numero 6 abbiamo dichiarato un array (di tipo NSMutableArray, quindi modificabile anche dopo la sua inizializzazione), che conterrà i valori letti dal database. Dalla riga 9 alla 12 abbiamo definito i metodi che ci serviranno in tale classe, che implementeremo fra poco. Da notare, inoltre, la classe importata alla riga 2: è necessaria per dire alla nostra classe di utilizzare la libreria che abbiamo importato all’inizio della guida. Apriamo ora il file “Data.m” e iniziamo ad inserire il seguente codice: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24

#import "Data.h" static sqlite3 *database = nil; @implementation Data @synthesize lista; // Inizializziamo l'oggetto della classe Data - (id)init:(NSString *)pathDB{ ! // carichiamo i valori dal database ! [self caricaValoriDaDB:pathDB]; return self; } // Ritorna la dimensione della lista (n° di elementi letti dal db) - (unsigned)getSize { return [lista count]; } // Ritorna l'oggetto ad una data posizione - (id)objectAtIndex:(unsigned)index { return [lista objectAtIndex:index]; }

Guida pratica a!’iPhone SDK"

106


La prima istruzione particolare compare alla riga 3, ed è la definizione dell’oggetto che ci servirà per creare la connessione con il database. Alla riga 10 viene dichiarato il primo metodo, “init”, che deve essere invocato quando si vuole inizializzare un oggetto appartenente alla classe Data. Alla riga 12 viene chiamiamo il metodo “caricaValoriDaDB”, che ha il compito di interfacciarsi con il database ed eseguire le query sui dati (vedremo fra poco la sua implementazione). Il “return self ” alla riga 13, infine, ritorna il puntatore dell”oggetto appena creato. Alla riga 17 definiamo “getSize”, un semplice metodo che ci ritorna la dimensione della lista, e quindi il numero di elementi letti dalla nostra query. Questo ci servirà quando andremo a definire la tabella. Infine, alla riga 22, definiamo un metodo che ci ritorna un oggetto presente ad una determinata posizione della nostra lista. Ad esempio, potremo recuperare il 5° elemento della nostra lista, per poi elaborarlo oppure mostrarlo all’utente. Dobbiamo ora implementare il metodo più complesso di questa classe, ovvero “caricaValoriDaDB”. Ecco il codice di tale metodo:

Guida pratica a!’iPhone SDK"

107


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36

// Carica i valori dal database passato come parametro - (void)caricaValoriDaDB:(NSString *)dbPath { ! NSLog(@"path: %@",dbPath); ! // lista temporanea ! NSMutableArray *listaTemp = [[NSMutableArray alloc] init]; ! // Oggetto che contiene i vari elementi NSMutableDictionary *dictionary; ! ! NSMutableString *idPersona;//id della persona ! NSMutableString *nome;//nome della persona ! NSMutableString *cognome;//cognome della persona ! ! if (sqlite3_open([dbPath UTF8String], &database) == SQLITE_OK) { ! ! // query che ricava i valori ! ! const char *sql = "select ID, Nome, Cognome from PERSONA"; ! ! sqlite3_stmt *selectstmt; ! ! ! ! if(sqlite3_prepare_v2(database, sql, -1, &selectstmt, NULL) == SQLITE_OK) { ! ! ! while(sqlite3_step(selectstmt) == SQLITE_ROW) { ! ! ! ! // ricaviamo i valori letti dalla query ! ! ! ! idPersona = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 0)]; ! ! ! ! nome = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 1)]; ! ! ! ! cognome = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 2)]; ! ! ! ! // inseriamo tutti i valori letti in un unico oggetto ! ! ! ! dictionary = [[NSMutableDictionary alloc] initWithObjectsAndKeys:idPersona, @"id", nome, @"nome", cognome, @"cognome", nil]; ! ! ! ! [listaTemp addObject:dictionary]; ! ! ! ! [dictionary release]; ! ! ! } ! ! } ! ! self.lista = listaTemp; ! ! [listaTemp release]; ! } ! else ! ! sqlite3_close(database); ! NSLog(@"tutto ok"); }

Iniziamo ad analizzare questo metodo. Partiamo dall’intestazione, in cui viene definito un parametro “dbPath”: questo è il percorso del nostro database. Esso lo definiremo in seguito, nella classe che gestisce la tabella. In questo tutorial il database sarà in locale, ovverò sarà fisicamente presente nella cartella del nostro progetto. Nulla vieta, comunque, di inserire un indirizzo remoto, che ci consenta di connetterci ad un database presente su un server.

Guida pratica a!’iPhone SDK"

108


Subito dopo, creiamo alcuni oggetti, che ci servono per gestire i dati ricavati dalle query. Abbiamo, infatti, un oggetto “dictionary”, che conterrà i vari elementi ricavati dall’interrogazione al database. Le stringhe “idPersona”, “nome”, “cognome”, infatti, servono per salvare i valori letti, e inserirli all’interno dell’oggetto appena menzionato. Alla riga 37 viene aperta la connessione con il database: essa si trova all’interno di un ciclo “if ”: se tale controllo da esito positivo, si possono elaborare i dati, altrimenti si passa alla fine del metodo, in quanto non è possibile instaurare una connessione con il database. Se la connessione è stata creata, possiamo creare la query che andremo poi ad eseguire (riga 39). Alla riga 42 eseguiamo poi tale query: anche in questo caso, se l’esecuzione ha avuto successo, possiamo ricavare i valori desiderati, altrimenti non verrà eseguita nessuna operazione. Il ciclo while (riga 44) ci permetterà di scorrere tutti i risultati della nostra query (che potrebbero essere, ovviamente, più di uno), fino al termine. Potete notare che i risultati vengono inseriti in un oggetto di tipo “NSMutableDictionary”: esso è come un grande contenitore, che ci permette di inserire valori associandoci un tag (quello che facciamo alla riga 50). Come vedete non si tratta di operazioni complesse, si tratta solo di capire come funziona il meccanismo, che potete poi variare a seconda delle vostre esigenze. Gli ultimi due metodi da inserire nel file “Data.m” sono i seguenti: 1 2 3 4 5 6 7 8 9

+(void)finalizeStatements { ! if(database) ! ! sqlite3_close(database); } -(void)dealloc { ! [lista release]; ! [super dealloc]; }

Il primo si occupa di concludere la query e di chiudere la connessione al database (va sempre messo), mentre il secondo è il classico “dealloc”. Abbiamo concluso con la definizione della classe “Data”. Ora vedremo come creare il nostro database e inserirlo nel progetto.

C REIAMO

IL DATABASE

Quello che dobbiamo andare a realizzare è un semplice database, con tecnologia SQLite. Per crearlo utilizzeremo un plug-in per Firefox, chiamato” SQLite Manager”, che potete trovare a questo indirizzo (https://addons.mozilla.org/en-US/firefox/addon/5817). In alternativa esistono alcuni programmi dedicati, come SQLiteManager (http://www.sqlabs.com/sqlitemanager.php), che è, però, a pagamento.

Guida pratica a!’iPhone SDK"

109


Dopo aver installato l’estensione, andiamo in “Strumenti -> SQLite Manager”, si avvierà il tool che ci permetterà di creare il nostro database. Clicchiamo sull’icona del foglio bianco per crare un nuovo database:

e inseriamo “persone” come nome per il file:

Guida pratica a!’iPhone SDK"

110


e scegliamo dove salvare il file (vi consiglio sulla Scrivania, così potrete recuperarlo subito in seguito). Abbiamo così creato il nostro database, che risulta però essere completamente vuoto. Dobbiamo, quindi, creare la tabella “Persone”. Per fare ciò, facciamo clic con il tasto destro su “Tables” che trovate nella parte sinistra della schermata, e selezioniamo “Create Table”:

Si aprirà una nuova schermata, in cui dovrete definire gli attributi della tabella. Ecco cosa dovete inserire:

Guida pratica a!’iPhone SDK"

111


e clicchiamo poi su “Yes” nel messaggio successivo che apparirà. Abbiamo inserito gli attributi necessari, ovvero nome, cognome e un identificativo univoco (id). Non ci resta che inserire dei valori nella tabella. Per fare ciò, andate nella sezione “Execute SQL” inserite le seguenti istruzioni: INSERT INSERT INSERT INSERT

INTO INTO INTO INTO

PERSONA PERSONA PERSONA PERSONA

(id,Nome,Cognome) (id,Nome,Cognome) (id,Nome,Cognome) (id,Nome,Cognome)

VALUES VALUES VALUES VALUES

('1','Giovanni','Verdi'); ('2','Paolo','Rossi'); ('3','Luca','Bianchi'); ('4','Andrea','Busi');

Un messaggio in “Last Error” vi comunicherà se vi sono stati errori nell’inserimento dei dati, oppure se tutto è andato per il verso giusto. Possiamo, infine, controllare i valori che abbiamo inserito, spostandoci nella sezione “Browse & Search”:

Guida pratica a!’iPhone SDK"

112


Abbiamo concluso! Chiudiamo pure il programmino, i cambiamenti sono già stati apportati al nostro database.

C ONCLUDIAMO L ’ APPLICAZIONE Torniamo ora ad XCode, e concludiamo lo sviluppo della nostra applicazione. Per prima cosa, dobbiamo inserire il database che abbiamo creato nel nostro progetto. Trasciniamo il file all’interno di XCode:

e nella schermata che apparirà inserite la spunta a “Copy items into destination group’s folder” e cliccate su “Add”

Guida pratica a!’iPhone SDK"

113


Siamo pronti per completare la nostra applicazione. Iniziamo aprendo il file “RootViewController.h” e inseriamo il seguente codice: 1 2 3 4 5 6 7 8

#import "Data.h" @interface RootViewController : UITableViewController { ! // Oggetto con la lista degli elementi letti dal db ! Data *dataList; } @end

Alla riga 5 abbiamo dichiarato la lista che conterrà gli elementi letti dal database. Per capirci, è quella che viene creata dal metodo “caricaValoriDaDB”, che abbiamo definito in precedenza. Passiamo ora al file “RootViewController.m”. Iniziamo con il metodo “viewDidLoad”, che, come ormai dovreste sapere, ci consente di eseguire delle operazioni al caricamento dell’applicazione. Ecco come dovete modificare tale metodo: 1 2 3 4 5 6 7 8 9 10

- (void)viewDidLoad { [super viewDidLoad]; ! self.title = @"Lista Autori"; ! //leggiamo il path del database ! NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"persone.sqlite"]; ! ! //creiamo la lista degli autori ! dataList = [[Data alloc] init:defaultDBPath]; }

Alla riga 4 impostiamo il titolo alla nostra tabella, mentre alla riga 6 definiamo il percorso del nostro database. A prima vista può sembrare complessa, ma essa non fa altro che rilevare il percorso in cui si trova l’applicazione (sia essa su iPhone Simulator che su iPhone fisico) e aggiungere a tale percorso “persone.sqlite”, che è proprio il database che abbiamo inserito nel nostro progetto. Alla riga 9, infine, inizializiamo la lista, passando alla funzione “init” proprio il percorso che abbiamo definito poche righe sopra. Dobbiamo, ora, definire i metodi necessari per settare la tabella. Abbiamo già visto questi metodi nei tutorial dedicati alle TableView, quindi non mi soffermerò troppo sulla spiegazione. Sempre all’interno del file “RootViewController.m”, scorretelo verso il fondo, e troverete i metodi del protocollo UITableView, che dovrete completare nel seguente modo:

Guida pratica a!’iPhone SDK"

114


1 2 3 4 5 6 7

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; }

// Customize the number of rows in the table view. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 8 return [dataList getSize]; 9 } 10 11 12 // Customize the appearance of table view cells. 13 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 14 15 static NSString *CellIdentifier = @"Cell"; 16 17 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 18 if (cell == nil) { 19 cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; 20 } 21 ! 22 ! NSDictionary *itemAtIndex = (NSDictionary *)[dataList objectAtIndex:indexPath.row]; 23 ! cell.textLabel.text = [itemAtIndex objectForKey:@"nome"]; 24 25 return cell; 26 }

I tre metodi sono i soliti che vanno inseriti quando si lavora con le UITableView. Concentriamoci un attimo sulle righe 22 e 23. Esse hanno il compito di ricavare un oggetto dalla lista “dataLista” (che contiene tutti i valori letti da database), per estrarne poi il nome desiderato (ovviamente vengono estratti tutti i nomi, dal primo all’ultimo). Potete vedere che dall’oggetto “itemAtIndex” viene estratto solo il nome: potremmo creare anche altre combinazioni, ad esempio con il cognome. Per fare ciò vi basterà modificare la riga 23 ad esempio nel seguente modo: 1 [itemAtIndex objectForKey:@"nome"];

Abbiamo concluso la nostra applicazione! Clicchiamo su “Build and Go!” e controlliamo che funzioni tutto in maniera corretta.

Guida pratica a!’iPhone SDK"

115


Guida pratica a!â&#x20AC;&#x2122;iPhone SDK"

116

Prova  

prova oporporrrrvregergtertrqtqertrewqt