20.04.2013 Views

Tutorial pratici per iPhone SDK v1.6 - Get a Free Blog

Tutorial pratici per iPhone SDK v1.6 - Get a Free Blog

Tutorial pratici per iPhone SDK v1.6 - Get a Free Blog

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

INDICE<br />

Prefazione! 8<br />

Parte 1: tutorial di base! 9<br />

Capitolo 1: Introduzione al <strong>SDK</strong> e ad XCode! 10<br />

Introduzione! 10<br />

Panoramica sul <strong>SDK</strong>! 10<br />

XCode! 11<br />

Capitolo 2: Come creare un nuovo progetto! 15<br />

I template di XCode! 15<br />

Creare un nuovo progetto! 17<br />

Interface Builder! 17<br />

Capitolo 3: Il nostro primo progetto, He"oWorld!! 20<br />

Creiamo la struttura grafica! 20<br />

Definiamo gli elementi e le azioni! 21<br />

Scriviamo il codice necessario! 24<br />

Facciamo nascondere la tastiera! 25<br />

Capitolo 4: TrashApp, gestiamo le immagini! 27<br />

Definiamo l’applicazione! 27<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 3


Definiamo l’aspetto grafico.! 28<br />

Implementiamo il movimento del logo! 31<br />

Il ripristino del logo! 33<br />

Capitolo 5: UIToolbar e auto-rotazione! 35<br />

Definiamo l’applicazione! 35<br />

Definiamo l’aspetto grafico! 35<br />

Scriviamo il codice necessario! 38<br />

Capitolo: 6: NSTimer e UIProgressView! 41<br />

Definiamo l’applicazione! 41<br />

Definiamo l’aspetto grafico! 42<br />

Scriviamo il codice! 44<br />

Capitolo 7: AccessContact, accediamo a"a rubrica! 48<br />

Definiamo il progetto! 48<br />

Definiamo la struttura grafica! 49<br />

Scriviamo il codice necessario! 50<br />

Capitolo 8: Creiamo un mini browser con le UIWebView! 53<br />

Creiamo la struttura grafica! 53<br />

Definiamo i componenti e co"eghiamo le azioni! 54<br />

Scriviamo il codice <strong>per</strong> aprire la pagina desiderata! 56<br />

Capitolo 9: UITableView, gestiamo le tabe"e! 58<br />

Parte 1: creiamo e definiamo la tabe"a! 58<br />

Creiamo un nuovo progetto! 58<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 4


Inseriamo il codice necessario! 59<br />

Parte 2: Inseriamo alcune funzionalità! 62<br />

Permettiamo la cance"azione di una riga! 62<br />

Rendiamo le ce"e selezionabili! 63<br />

Parte 3: Implementiamo la ricerca! 65<br />

A$iungiamo il box di ricerca! 65<br />

Modifichiamo i metodi già esistenti! 66<br />

Implementiamo la ricerca! 68<br />

Capitolo 10: gestiamo più viste (file “.xib” multipli)! 71<br />

Creiamo un nuovo progetto! 71<br />

Definiamo la prima vista! 72<br />

Definiamo la “VistaDue”! 74<br />

Scriviamo il codice necessario! 75<br />

Capitolo 11: Come creare una TabBar Application! 78<br />

Parte 1: la struttura di base! 78<br />

Creiamo una TabBar “pulita”! 78<br />

Definiamo le due viste! 79<br />

Creiamo l’aspetto grafico de"e due viste! 80<br />

Impostiamo la TabBar! 83<br />

Parte 2: Inseriamo una NavigationBar! 87<br />

Creiamo un nuovo elemento <strong>per</strong> la TabBar! 87<br />

Definiamo l’aspetto del nuovo elemento! 89<br />

Implementiamo due viste di dettaglio! 92<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 5


Definiamo l’aspetto de"e due viste di dettaglio! 93<br />

Come richiamare le due viste via codice! 96<br />

Capitolo 12: XML! 99<br />

Cosa è XML?! 99<br />

XML nel <strong>SDK</strong> di <strong>iPhone</strong>! 101<br />

Creiamo la struttura grafica! 101<br />

Scriviamo il codice necessario! 103<br />

Capitolo 13: SQL! 108<br />

Definiamo un nuovo progetto! 108<br />

Definiamo la classe “Data”! 110<br />

Creiamo il database! 114<br />

Concludiamo l’applicazione! 118<br />

Parte 2: semplici applicazioni! 122<br />

Capitolo 14: Creiamo un semplice lettore di feed RSS! 123<br />

Creiamo un nuovo progetto! 123<br />

Definiamo le azioni del parser! 125<br />

Concludiamo l’applicazione! 128<br />

Un piccolo miglioramento! 129<br />

Capitolo 15: Creiamo un client <strong>per</strong> Twitter!! 132<br />

Parte 1: connettiamoci a Twitter! 132<br />

impostiamo la libreria “MGTwitterEngine”! 132<br />

Definiamo la vista di caricamento! 136<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 6


Creiamo la classe “Tweet”! 137<br />

Definiamo la classe “SampleTwitterClientViewContro"er”! 138<br />

Le$iamo la timeline! 140<br />

Parte 2: Creiamo la tabe"a con i tweet letti! 143<br />

Creiamo la ce"a <strong>per</strong>sonalizzata! 145<br />

Definiamo la classe de"a tabe"a! 149<br />

Completiamo l’applicazione! 151<br />

Parte 3: Il salvata$io dei dati! 157<br />

Gestiamo il caricamento / salvata$io dei dati! 159<br />

Capitolo 16: Realizziamo il nostro “Brushes”! 162<br />

Parte 1: Creiamo la tavola grafica! 162<br />

Creiamo un nuovo progetto! 162<br />

Definiamo l’aspetto grafico de"’applicazione! 163<br />

Definiamo i metodi necessari! 166<br />

Parte 2: Inseriamo i setta$i! 170<br />

A$iungiamo le impostazioni! 170<br />

Scriviamo il codice necessario! 174<br />

Inseriamo il salvata$io del disegno! 177<br />

Bibliografia! 181<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 7


Prefazione<br />

Questo libro racchiude tutti i tutorial che ho creato sulla programmazione <strong>per</strong> <strong>iPhone</strong> e iPod<br />

Touch. Non vuole essere un manuale esauriente o sostituirsi alla documentazione ufficiale Apple,<br />

ma solo uno strumento <strong>per</strong> chi è alle prime armi, oppure <strong>per</strong> chi vuole imparare qualcosa<br />

che ancora non sa.<br />

Troverete una serie di guide pratiche, da seguire passo <strong>per</strong> passo, commentate e spiegate, <strong>per</strong><br />

consentire a tutti di imparare e capire quello che viene fatto. Il libro è diviso in due sezioni: la<br />

prima vi presenterà dei tutorial sugli aspetti e sui componenti base della programmazione <strong>per</strong><br />

<strong>iPhone</strong>, mentre la seconda parte vi fornirà alcuni tutorial in cui verranno create delle semplici<br />

applicazioni complete, in modo che abbiate un quadro d’insieme generale.<br />

Ringrazio chiunque legga queste pagine, s<strong>per</strong>ando di potervi aiutare in un vostro scopo, sia lavorativo<br />

o <strong>per</strong> pura passione (come la mia).<br />

Ringrazio la mia fidanzata, che mi ha sempre sopportato e sostenuto, seppur non sappia niente<br />

di programmazione!<br />

Ringrazio Fabiano Confuorto, fondatore e amministratore di iSpazio, una stupenda community<br />

che mi ha fatto scoprire il mondo <strong>iPhone</strong>, e che mi ha dato l’opportunità di creare e pubblicare<br />

i miei primi tutorial.<br />

Ringrazio Steve Jobs, <strong>per</strong> aver creato il Mac e l’<strong>iPhone</strong>, cercando sempre la <strong>per</strong>fezione nelle cose.<br />

E ricordatevi, solo essendo curiosi e affamati è possibile scoprire e creare qualcosa di nuovo e<br />

veramente innovativo.<br />

“Siate affamati, siate fo"i.”<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 8


Parte 1:<br />

tutorial di base<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 9


Capitolo 1: Introduzione al <strong>SDK</strong> e ad XCode<br />

INTRODUZIONE<br />

Con il rilascio del firmware 2.0, Apple ha segnato una svolta nel settore mobile: non era mai<br />

stato così semplice sviluppare e vendere le proprie applicazioni. Per <strong>per</strong>mettere tutto ciò, Apple<br />

ha creato AppStore, uno spazio che si integra al già famoso e collaudato iTunes Store. Qualsiasi<br />

sviluppatore, indipendente o azienda già affermata, può pubblicare le proprie creazioni<br />

semplicemente acquistando una licenza annua, al prezzo di 99$ (79€ <strong>per</strong> noi europei). Quali<br />

sono i vanta$i legati a"’acquisto di una licenza? Sono molti, e valgono il prezzo da pagare. La cosa<br />

più importante è, come già detto, la possibilità di vendere le proprie applicazioni in AppStore.<br />

Ci sono, <strong>per</strong>ò, altri vantaggi: la possibilità di scaricare e installare le versioni beta dei nuovi<br />

firmware (<strong>per</strong> testare la compatibilità delle proprie applicazioni); la possibilità di installare i<br />

propri progetti anche sull’<strong>iPhone</strong> / iPod Touch direttamente da XCode (cosa che non è possibile<br />

senza licenza); l’accesso ad un forum specifico in cui saranno es<strong>per</strong>ti Apple a dare risposte e<br />

ad aiutare gli sviluppatori in difficoltà; la disponibilità di una documentazione più ampia e più<br />

dettagliata. Come vedete non si tratta di sciocchezze.<br />

Ma come si sviluppano le applicazioni? Il tutto è davvero molto semplice (in pieno stile Apple): con<br />

il firmware 2.0, infatti, è stato rilasciato un <strong>SDK</strong> (Software Development Kit) ufficiale, che<br />

integra tutti gli strumenti necessari <strong>per</strong> creare applicazioni e giochi <strong>per</strong> <strong>iPhone</strong> e iPod Touch.<br />

Questo <strong>SDK</strong> è liberamente scaricabile dall’iOS Dev Center<br />

(http://develo<strong>per</strong>.apple.com/devcenter/ios/index.action), previa registrazione gratuita (ma si<br />

può accedere alla sezione anche con il proprio account di iTunes). L’iOS Dev Center è l’area di<br />

Apple dedicata agli sviluppatori (ovviamente di applicazioni <strong>per</strong> <strong>iPhone</strong>), in cui si può trovare<br />

davvero tantissimo materiale molto utile: esempi con codice ben commentato, documentazione<br />

delle librerie, documenti teorici, video, e molto altro ancora.<br />

Come ho già detto, <strong>per</strong> pubblicare applicazioni in AppStore è necessario disporre della licenza<br />

ufficiale. Questo, <strong>per</strong>ò, non basta <strong>per</strong> vedere pubblicate le proprie creazioni: ogni applicazione,<br />

infatti, passa sotto il controllo di Apple, che decide se accettarle o meno. Le applicazioni presenti<br />

in AppStore, infatti, devono rispettare il contratto del <strong>SDK</strong>, che prevede alcune limitazioni:<br />

è vietato, ad esempio, duplicare funzioni già presenti nel S.O. dell’<strong>iPhone</strong> (come l’invio di<br />

SMS e MMS), oppure sono vietate applicazioni con contenuto a sfondo sessuale o violento.<br />

Non pensate, quindi, di poter ingannare Apple: c’è chi si è visto rifiutare la propria applicazione<br />

anche <strong>per</strong> una semplice icona.<br />

PANORAMICA SUL <strong>SDK</strong><br />

Dopo aver scaricato e installato l’<strong>SDK</strong> (un’immagine dmg di circa 3 GByte), troverete tutto il<br />

necessario <strong>per</strong> sviluppare nella cartella “/Develo<strong>per</strong>/Applications”. Gli strumenti (davvero molto<br />

potenti) che Apple mette a disposizione sono i seguenti:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 10


• Dashcode, è un utile tool con cui potremo creare pagine web, widget (anche <strong>per</strong> la Dashboard<br />

di Mac OS X) e altro;<br />

• Instruments, <strong>per</strong>mette di analizzare e valutare le prestazioni delle nostre applicazioni (in<br />

termini di consumo di memoria, impiego del processore, etc). È destinato, ovviamente, agli<br />

sviluppatori più es<strong>per</strong>ti.<br />

• Interface Builder, grazie a questa applicazione sarà davvero un gioco da ragazzi creare<br />

l’aspetto grafico dei nostri programmi. Potremo inserire qualsiasi tipo di oggetto (bottoni,<br />

label, viste) semplicemente trascinando gli oggetti nella nostra schermata.<br />

• Quartz Composer, è un tool che <strong>per</strong>mette di creare animazioni ed effetti grafici, da utilizzare<br />

poi in altri programmi.<br />

• XCode, è l’ambiente di sviluppo vero e proprio. Sarà qui, infatti, che andremo a creare i nostri<br />

progetti, scrivere il codice e compilare il tutto. È lo strumento, insieme ad Interface<br />

Builder, che utilizzeremo di più.<br />

XCODE<br />

Analizziamo, ora, come si presenta XCode. Aprendo un progetto (vedremo nel capitolo 2 come<br />

crearne un nuovo) otterremo la seguente schermata:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 11


Potete notare tre sezioni principali: a sinistra troviamo “Groups & Files”, in cui abbiamo tutti i<br />

file che compongono il nostro progetto. Troveremo, quindi, le classi, le immagini inserite, i<br />

framework utilizzati. A destra, invece, possiamo vedere l’editor del codice, che ci assisterà e ci<br />

<strong>per</strong>metterà di scrivere il nostro codice. La barra in alto, infine, ci offre la possibilità di compilare<br />

ed installare la nostra applicazione, sul dispositivo che preferiamo: il nostro <strong>iPhone</strong> (solo nel<br />

caso in cui abbiamo la licenza ufficiale) oppure l’<strong>iPhone</strong> Simulator (un simulatore che ci <strong>per</strong>metterà<br />

di testare le nostre applicazioni comodamente sul Mac, senza dover installare nulla sul<br />

nostro <strong>iPhone</strong>).<br />

Il menù a tendina presente a sinistra della barra ci <strong>per</strong>mette di scegliere velocemente alcune<br />

opzioni, molto utili in fase di compilazione ed installazione. Se lo apriamo troviamo le seguenti<br />

voci (che ovviamente variano a seconda della versione di <strong>SDK</strong> che avete installato nel vostro<br />

Mac):<br />

La prima parte ci <strong>per</strong>mette di scegliere se installare la nostra applicazione sul simulatore oppure<br />

su un device fisico. Ovviamente all’inizio del vostro progetto testerete l’applicazione solo sul<br />

simulatore, ma poi sarà molto importante controllare che tutto funzioni correttamente anche<br />

sul dispositivo vero e proprio.<br />

La seconda impostazione riguarda “Active Configuration”: selezionando l’opzione “Debug” otterremo<br />

un’applicazione più pesante, progettata <strong>per</strong> essere testata e corretta (proprio in quella<br />

che viene definita fase di debug); la versione “Release”, invece, è molto più leggera ed è pronta<br />

<strong>per</strong> essere rilasciata e pubblicata in AppStore.<br />

Se cliccate due volte sul nome del progetto si aprirà una finestra in cui vi verranno mostrate<br />

tutte le proprietà del vostro progetto. Alcune imparerete a conoscerle durante la lettura, altre<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 12


invece non le utilizzerete mai nella vostra vita (a meno che non andiate a lavorare al campus di<br />

Cu<strong>per</strong>tino di Apple, e ve lo auguro con tutto il cuore).<br />

Concentriamoci, <strong>per</strong>ò, su due voci importantissime. La prima è “Base <strong>SDK</strong>”, che trovate nelle<br />

prime posizioni:<br />

essa indica la versione dell’<strong>SDK</strong> che stiamo utilizzando. Se scaricate qualche progetto e vi appare<br />

la scritta “Base <strong>SDK</strong> Missing”, dovete semplicemente entrare in questa opzione e selezionare<br />

la vostra versione di <strong>SDK</strong>. Questa serve solamente <strong>per</strong> far capire ad XCode che stiamo<br />

lavorando con l’<strong>SDK</strong> di iOS, e non quello <strong>per</strong> Mac OS X.<br />

Un’altra opzione di fondamentale importanza la trovare un po’ più sotto, si chiama “iOS Deployment<br />

Target”:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 13


Qui andremo a selezionare la versione del firmware con cui vogliamo che sia compatibile la nostra<br />

applicazione. Questo è necessario in quanto spesso, con il rilascio di nuovi firmware, vengono<br />

aggiunte anche nuove funzioni all’<strong>SDK</strong> (le API). Quindi, un’applicazione scritta e compilata<br />

<strong>per</strong> il firmware 4.2 potrebbe non funzionare con una versione inferiore del firmware (spesso<br />

è proprio impossibile installarla, in quanto l’AppStore controlla questa compatibilità in fase<br />

di installazione). Al contrario, se compiliamo l’applicazione <strong>per</strong> la versione 3.0 funzionerà sicuramente<br />

(a meno che non utilizziate delle API con alcuni bug) sulla 4.2. È importante, quindi,<br />

scegliere con cura la versione da utilizzare, <strong>per</strong> non escludere parte di utenza dall’utilizzo della<br />

nostra applicazione.<br />

Per ora è buona norma rendere le vostre applicazioni compatibili dal firmware 3.1 in su, in<br />

modo tale da non escludere nessun device (i primi <strong>iPhone</strong> EDGE e gli iPod Touch di 1° generazione,<br />

infatti, non possono installare iOS 4).<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 14


Capitolo 2: Come creare un nuovo progetto<br />

Abbiamo dato un’occhiata al <strong>SDK</strong> e ad XCode. È venuto il momento di iniziare a vedere gli<br />

strumenti che XCode ci mette a disposizione <strong>per</strong> realizzare i nostri progetti.<br />

In questo capitolo vedremo come creare un nuovo progetto, quali template XCode ci mette a<br />

disposizione e le caratteristiche principali di Interface Builder.<br />

I TEMPLATE DI XCODE<br />

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

Potete notare che XCode ci fornisce vari template, ovvero delle strutture già pronte, che ci<br />

<strong>per</strong>metteranno di creare applicazioni sullo stile di quelle native. Non dovremo <strong>per</strong>dere tempo,<br />

quindi, <strong>per</strong> replicare lo stile delle altre applicazioni, <strong>per</strong>ché è Apple stessa che ce li mette a disposizione.<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 15


( Navigation-Based! ! Tab Bar Application! ! ! Utility Application<br />

Analizziamo, ora, i vari template che ci vengono forniti.<br />

• Navigation-Based Application, genera un’applicazione in cui possiamo navigare in sotto-livelli.<br />

Per farvi un esempio, pensate alla struttura di “Impostazioni” nel vostro <strong>iPhone</strong>: avete<br />

una barra in alto che visualizza il titolo della sezione corrente, e vi <strong>per</strong>mette, tramite un<br />

bottone, di tornare alla sezione precedente. Questa barra viene chiamata “Navigation Bar”.<br />

Utile <strong>per</strong> creare applicazioni con tabelle, in cui vogliamo mostrare anche le informazioni<br />

sui vari elementi.<br />

• OpenGL ES Application, questa è sicuramente la tipologia più complessa, in quanto si basa<br />

sulla tecnologia OpenGL (http://it.wikipedia.org/wiki/OpenGL), sfruttata principalmente<br />

<strong>per</strong> realizzare videogiochi o animazioni grafiche complesse. In questo libro non analizzeremo<br />

questa tipologia di applicazioni.<br />

• Tab Bar Application, fornisce un’applicazione con la “tab bar”, ovvero la barra nera composta<br />

da più sezioni (ad esempio quella che trovate nell’applicazione nativa “Musica”).<br />

• Utility Application, questa tipologia implementa un menù che viene richiamato ruotando la<br />

schermata principale. Anche in questo caso, potete trovare una similitudine con l’applicazione<br />

“Meteo”: se premete sulla “i” presente a fondo pagina, la schermata ruoterà e vi <strong>per</strong>metterà<br />

di modificare i settaggi dell’applicazione.<br />

• View-Based Application, fornisce un’applicazione vuota, senza nessuna implementazione<br />

particolare. Questo template è composto da una finestra, chiamata “MainWindow”, e una<br />

vista, “[nome_progetto]ViewController”, che viene caricata proprio dalla finestra principale.<br />

Sarà questo punto di partenza <strong>per</strong> tutti i nostri tutorial.<br />

• Window-Based Application, è molto simile al caso precedente, ma il template fornito è composto<br />

solamente da una finestra (non è presente quindi la vista “[nome_progetto]ViewController”).<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 16


CREARE UN NUOVO PROGETTO<br />

In ogni tutorial che vedremo, sarà necessario creare un nuovo progetto. Per fare ciò, vi basterà<br />

aprire XCode, selezionare “File -> New Project...”, si aprirà la finestra con la scelta del template,<br />

che abbiamo appena analizzato. Scegliete il template desiderato (generalmente sarà View-<br />

Based Application), cliccate su “Choose..” e nel box successivo inserite il nome del nostro progetto.<br />

Finito!<br />

INTERFACE BUILDER<br />

Scorrendo la sezione “Groups & Files” possiamo vedere tutti i file che XCode ha già inserito<br />

<strong>per</strong> noi. Nel capitolo 3 vedremo come creare la nostra prima applicazione (il classico HelloWorld),<br />

ora ci limitiamo ad analizzare le caratteristiche principali dell’Interface Builder.<br />

Facciamo doppio clic su “[nome_progetto]ViewController.xib”, nella cartella “Resources”, e si<br />

aprirà Interface Builder.<br />

Ci ritroveremo con una situazione simile a questa:<br />

Potete notare vari strumenti sul vostro desktop: la libreria, la schermata della nostra applicazione<br />

(<strong>per</strong> ora completamente grigia), ed altri strumenti.<br />

Analizziamo ora questi componenti.<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 17


• Library, è la libreria da cui possiamo inserire tutti gli oggetti che desideriamo. Se non è già<br />

a<strong>per</strong>ta, ci basterà andare in “Tools -> Library” e si aprirà<br />

una finestra come quella a lato. Scorrendo la barra laterale,<br />

potete notare moltissimi componenti, come bottoni,<br />

label di testo, viste, barre e molto altro. Tutti questi elementi<br />

potranno essere utilizzati nelle nostre applicazioni.<br />

Per inserirli basta trascinare un componente nella schermata<br />

dell’applicazione, e collocarlo a proprio piacere<br />

(questo è vero <strong>per</strong> tutti i componenti tranne i “Controllers”,<br />

che potrete riconoscere <strong>per</strong>ché hanno uno sfondo<br />

giallo).<br />

• Vista o finestra, è la nostra vista, ovvero la finestra che verrà visualizzata sull’<strong>iPhone</strong>. Potremo<br />

<strong>per</strong>sonalizzarla a nostro piacimento, e impareremo nei capitoli successivi come fare.<br />

L’unica cosa che vi faccio notare, è la freccia presente a destra del nome della vista:<br />

Se provate a cliccarla, noterete che la vista ruota: questo <strong>per</strong>ché sarà possibile implementare<br />

la possibilità di ruotare la nostra applicazione quando l’utente ruota il proprio <strong>iPhone</strong>.<br />

Vedremo in dettaglio questo aspetto in un tutorial successivo.<br />

• Panne"o documenti, questo pannello vi mostra tutti i componenti del vostro file xib. All’inizio<br />

vi potrà sembrareinutile, <strong>per</strong>ò quando l’applicazione<br />

inizierà a diventare complessa, vi sarà molto<br />

utile <strong>per</strong> ritrovare tutti i componenti della vostra<br />

finestra.<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 18


• Inspector, è sicuramente la parte più importante di Interface Builder, in quanto ci <strong>per</strong>mette<br />

di impostare qualsiasi proprietà, relativa ad ogni oggetto (dalla vista al singolo bottone).<br />

Potremo, quindi, modificare l’aspetto degli oggetti, collegare le azioni, modificarne la dimensioni.<br />

Insomma, potrete agire su moltissimi aspetti (il tutto senza scrivere una riga di<br />

codice).<br />

L’Inspector è composto da 4 parti:<br />

✴Attributes, qui possiamo variare gli attributi generici dei nostri oggetti, ad esempio il<br />

colore, la dimensione del font, ed altre proprietà che impareremo poco alla volta.<br />

✴Connections, è uno dei pannelli principali. Qui andremo a collegare le azioni agli oggetti.<br />

Cosa significa? Ve lo spiego con un esempio. Supponiamo di avere un bottone<br />

nella nostra vista, e vogliamo che quando viene premuto venga scritto “Ciao” in una<br />

casella di testo. Creeremo, quindi, un’azione, che si occu<strong>per</strong>à di scrivere “Ciao”. Dovremo,<br />

poi, collegare questa azione al bottone, in modo che quando l’utente preme il<br />

bottone, viene eseguito il comportamento desiderato. Vedrete che con i prossimi tutorial<br />

tutto questo sarà più familiare.<br />

✴Size, questa sezione <strong>per</strong>mette, come dice la parola stessa, di modificare le dimensioni<br />

dell’oggetto, e di modificarne anche la posizione e l’ancoraggio (ovvero dove deve essere<br />

fissato, questo sarà fondamentale quando implementeremo la rotazione della<br />

schermata).<br />

✴Identity, in questo pannello sono presenti alcune voci relative al progetto e al file che<br />

stiamo modificando. Noi non utilizzeremo mai questo pannello, quindi potete anche<br />

non considerarlo.<br />

Abbiamo così completato la panoramica sull’Interface Builder. Mi pare inutile, <strong>per</strong> ora, dilungarmi<br />

in altri aspetti, che vi saranno sicuramente più chiari e familiari con un po’ di pratica. In<br />

pochissimo tempo, non riuscirete più a fare a meno di Interface Builder!<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 19


Capitolo 3: Il nostro primo progetto, HelloWorld!<br />

In questo capitolo realizzeremo la nostra prima applicazione, il classico HelloWorld! Chiederemo<br />

all’utente il proprio nome (ad esempio Tizio) e alla pressione di un bottone faremo apparire<br />

il messaggio “Ciao Tizio”. Niente di complicato quindi, <strong>per</strong>ò cercate di capire bene tutti i<br />

passaggi, in modo da non avere lacune su queste cose basilari.<br />

CREIAMO LA STRUTTURA GRAFICA<br />

Iniziamo quindi creando un nuovo progetto di tipo “View-Based Application” e chiamiamolo<br />

“HelloWorld”. Apriamo quindi il file “HelloWorldViewController.xib”, che avvierà anche l’Interface<br />

Builder. Ora dobbiamo creare la struttura grafica, che deve essere simile a questa:<br />

Come potete osservare, ci sono tre componenti principali:<br />

1.una UITextField in cui l’utente potrà inserire il proprio nome;<br />

2.una UIButton, con la scritta “Saluta!”, che l’utente dovrà premere <strong>per</strong> far apparire il saluto;<br />

3.due UILabel, una con la scritta “Nome” (e questa serve solo <strong>per</strong> rendere più intuitivo il<br />

nostro programma), l’altra posta a centro schermo (che contiene la stringa Label). È importante<br />

impostare le dimensioni di questa ultima label in modo che occupi tutta la larghezza<br />

della vista, altrimenti avremo problemi quando andremo a stampare il messaggio di saluto<br />

in seguito.<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 20


Tramite “Attribute Inspector” possiamo definire alcune proprietà <strong>per</strong> questi oggetti. Selezioniamo<br />

ad esempio la UITextField, e impostiamo i seguenti valori:<br />

• “Capitalize”: “Words” (ovvero quando l’utente inizia a digitare il proprio nome la prima lettera<br />

viene scritta in maiuscolo);<br />

• “Corrections”: “No” (disabilitiamo la correzione automatica <strong>per</strong> questo campo);<br />

• Spuntiamo l’opzione “Clear When Editing Begins” (cancellerà il contenuto già presente non<br />

appena l’utente seleziona il campo).<br />

A vostro piacere potete anche impostare altre proprietà, provatene alcune <strong>per</strong> prendere un po’<br />

più di confidenza.<br />

Prima di proseguire, diamo un’occhiata a ciò che compone questo file (lo potete trovare nel<br />

pannello dei documenti):<br />

Potete notare tre elementi, che XCode ha già definito <strong>per</strong> noi.<br />

• File’s Owner, come dice la parola stessa, è il proprietario del file. È, in sostanza, la classe che<br />

gestisce la nostra finestra, ovvero che gestisce ogni singolo aspetto. Nel nostro caso sarà la<br />

classe “HelloWorldViewController”, dove poi andremo a scrivere il codice necessario.<br />

• First Responder, <strong>per</strong> ora non è un componente che ci interessa, <strong>per</strong>ò sappiate che si occupa,<br />

ad esempio, della gestione del multi-touch.<br />

• View, è la nostra vista, ovvero la schermata che abbiamo definito. In questo caso ne abbiamo<br />

solo una, ma nulla ci vieta di definirne svariate e richiamarle poi a nostro piacimento.<br />

DEFINIAMO GLI ELEMENTI E LE AZIONI<br />

Dobbiamo ora definire gli elementi e le azioni necessarie. Il procedimento sarà sempre questo,<br />

ovvero definire gli elementi via codice e poi collegarli ad oggetti di Interface Builder. Salviamo<br />

tutto e chiudiamo Interface Builder, tornando così in XCode.<br />

Nella cartella “Classes” noteremo quattro file: due con estensione “.h” e due con estensione<br />

“.m”. I file “.h” stanno ad indicare le classi di intestazione, ovvero dove vengono definiti i me-<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 21


todi e i componenti necessari, ma non vi è alcuna implementazione dei metodi. Saranno i file<br />

con estensione “.m” a contenere tutte le implementazioni dei metodi, ovvero il codice delle varie<br />

funzioni.<br />

Iniziamo, quindi, aprendo il file “He"oWorldViewContro"er.h”, in cui dovremo definire gli oggetti<br />

che ci serviranno. Nel nostro esempio, saranno due gli elementi da definire: la UITextField in<br />

cui l’utente inserisce il proprio nome (e da cui noi dobbiamo leggerne il valore), e la UILabel in<br />

cui scriveremo il saluto. Dovremo, poi, definire un’azione, quella che verrà richiamata alla pressione<br />

del bottone.<br />

Ecco il codice da inserire:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

12<br />

13<br />

14<br />

#import <br />

@interface HelloWorldViewController : UIViewController {<br />

! IBOutlet UITextField *fieldNome;<br />

! IBOutlet UILabel *labelSaluto;<br />

}<br />

-(IBAction)saluta;<br />

@pro<strong>per</strong>ty (nonatomic, retain) IBOutlet UITextField *fieldNome;<br />

@pro<strong>per</strong>ty (nonatomic, retain) IBOutlet UILabel *labelSaluto;<br />

@end<br />

Abbiamo dichiarato una UITextField e una UILabel, proprio i due componenti che ci servono.<br />

Possiamo notare che entrambe le dichiarazioni sono precedute dalla clausola “IBOutlet”, che<br />

indica ad Interface Builder che è possibile collegare questo metodo ad un elemento grafico.<br />

Questo è necessario <strong>per</strong>ché, come vedrete fra poco, ci <strong>per</strong>metterà di collegare l’oggetto creato<br />

tramite Interface Builder con quello dichiarato in XCode.<br />

Dopo queste due dichiarazioni, trovate l’intestazione del metodo “saluta”, e anche in questo<br />

caso trovate una clausola ”IBAction”: anche questa sta a significare che l’azione è collegata ad<br />

un componente di Interface Builder.<br />

Le due pro<strong>per</strong>ty, poi, servono <strong>per</strong> poter utilizzare senza problemi le proprietà degli oggetti che<br />

abbiamo definito.<br />

Ora salviamo il file (Cmd + S) e riapriamo “HelloWorldViewController.xib”. Dobbiamo collegare<br />

questi componenti con quelli effettivamente inseriti nella nostra vista.<br />

Dal pannello dei documenti selezionate il componente “File’s Owner”. Aprendo il “Connections<br />

Inspector” dovreste vedere un pannello come questo:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 22


Potete notare che sono presenti i componenti che abbiamo definito via codice! Ora non dobbiamo<br />

fare altro che collegarli agli elementi adeguati. Prendiamo il pallino a fianco di “fieldNome”<br />

e trasciniamolo fino alla UITextField della nostra vista. Avremo così<br />

collegato i due elementi! Ripetiamo la stessa o<strong>per</strong>azione con “labelSaluto”,<br />

trascinando il pallino sulla UILabel posta a centro schermo.<br />

Stessa o<strong>per</strong>azione va eseguita <strong>per</strong> l’azione “saluta”. Collegatela al bottone, ma<br />

quando rilasciate il bottone del mouse vi apparirà un menù come quello che<br />

trovate qui a fianco.<br />

Sono tutte le azioni che può gestire un bottone. Noi selezioniamo “Touch<br />

Up Inside”, ovvero un azione di click e rialscio (un singolo tap insomma).<br />

Volendo potremmo scegliere di avviare l’azione quando il bottone viene rilasciato,<br />

ma <strong>per</strong> il nostro scopo non cambia niente.<br />

Se avete eseguito tutto correttamente avrete un pannello “Connections Inspector” come questo:<br />

Abbiamo così concluso la definizione dei componenti della nostra applicazione. Salviamo tutto<br />

e chiudiamo Interface Builder.<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 23


SCRIVIAMO IL CODICE NECESSARIO<br />

Dobbiamo ora implementare il metodo “saluta”, che si occu<strong>per</strong>à di leggere il nome inserito dall’utente<br />

e stampare il messaggio di benvenuto sulla label predisposta.<br />

Apriamo il file “HelloWorldViewController.m” e inseriamo il seguente codice:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

12<br />

13<br />

14<br />

15<br />

16<br />

17<br />

18<br />

19<br />

20<br />

21<br />

22<br />

23<br />

24<br />

25<br />

26<br />

27<br />

#import "HelloWorldViewController.h"<br />

@implementation HelloWorldViewController<br />

// importiamo i componenti di cui abbiamo definito le pro<strong>per</strong>ty<br />

@synthesize fieldNome, labelSaluto;<br />

// azione richiamata alla pressione del bottone<br />

-(IBAction)saluta{<br />

! // leggiamo la stringa contenuta nella UITextField (il nome dell'utente)<br />

! NSString *nome = fieldNome.text;<br />

!<br />

! if ([nome length] == 0){<br />

! ! // l'utente non ha inserito nessun nome<br />

! ! labelSaluto.text = [[NSString alloc]<br />

initWithFormat:@"Ciao anonimo!"];<br />

! }else{<br />

! ! // salutiamo l'utente<br />

! ! labelSaluto.text = [[NSString alloc]<br />

initWithFormat:@"Ciao %@",nome];<br />

! }<br />

}<br />

- (void)dealloc {<br />

! [labelSaluto dealloc];<br />

! [fieldNome dealloc];<br />

!<br />

[su<strong>per</strong> dealloc];<br />

}<br />

Analizziamo il codice poco alla volta. L’istruzione presente alla riga 3 che ha il compito di caricare<br />

gli elementi di cui prima abbiamo definito le “pro<strong>per</strong>ty”. Potrebbe sembrare un po’ strana,<br />

ma <strong>per</strong> ora prendetela come regola.<br />

Dalla riga 9 alla 20 troviamo la definizione del metodo “saluta”. In tale metodo, non facciamo<br />

altro che leggere il nome inserito dall’utente (tramite “fieldNome.text”, che ci restituisce la<br />

stringa contenuta nella UITextField) e assegnarlo alla variabile “nome” (riga 11). Tramite una<br />

costrutto “if” (dalla riga 13 alla 19) andiamo poi a controllare se tale stringa è vuota (e quindi<br />

l’utente ha premuto il tasto senza inserire nessun nome) oppure se vi è un valore. Ovviamente<br />

inseriamo due messaggi di saluto diversi a seconda del caso.<br />

Particolare attenzione merita parte dell’istruzione alla riga 18, ed in particolare questo pezzo di<br />

codice: “@"Ciao %@",nome”.<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 24


• “@”, la prima chiocciola sta ad indicare che ciò che segue è una stringa. La sintassi è sempre<br />

la stessa, è può essere schematizzata nel seguente modo: @”stringa_desiderata”. Dovrete<br />

sempre utilizzare questo formato quando istanziate una stringa.<br />

• “%@”, quando trovate un % in una stringa, significa che li ci andrà il valore di una determinata<br />

variabile. Non a caso dopo la stringa trovare la variabile “nome”: il contenuto di tale<br />

variabile nome andrà inserito al posto di %@. Se avessimo dovuto inserire il valore di una<br />

variabile di tipo float avremmo usato la sintassi %f. Vedremo parecchi esempi nei prossimi<br />

tutorial.<br />

Il metodo “dealloc”, infine, è quello che si occupa di liberare la memoria che abbiamo utilizzato.<br />

L’Objective-C, infatti, non prevede un gestore della memoria come avviene invece in Java<br />

(tramite il Garbage Collector). Sarà compito degli sviluppatori, quindi, liberare la memoria dagli<br />

oggetti che non servono più. In questo metodo dovrete sempre inserire i componenti che<br />

avete utilizzato, richiamando <strong>per</strong> ognuno il metodo “dealloc”. Nell’esempio potete vedere che<br />

liberiamo dalla memoria gli oggetti “labelSaluto” e “fieldNome”.<br />

Possiamo ora cliccare su “Build and Go!”, se non abbiamo commesso errori nell’inserire il codice<br />

si avvierà l’<strong>iPhone</strong> Simulator e potremo testare il nostro programma!<br />

FACCIAMO NASCONDERE LA TASTIERA<br />

Se provate ad inserire un nome e a premere il tasto “Invio” della tastiera che appare sull’<strong>iPhone</strong>,<br />

noterete che essa non si chiude. Si tratta di un bug? La risposta è no. È normale, in quanto<br />

non abbiamo implementato niente che chiuda tale tastiera.<br />

Per sistemare questo problema, apriamo il file “HelloWorldViewController.h” e modifichiamo<br />

l’intestazione nella seguente maniera:<br />

1 @interface HelloWorldViewController : UIViewController {<br />

Potete notare che abbiamo aggiunto ““, ovvero la nostra classe deve<br />

implementare il delegato della classe UITextField. Parleremo più avanti di cosa siano i delegati,<br />

<strong>per</strong> ora sappiate che sono dei comportamenti comuni a delle classi di oggetti.<br />

Fatto ciò, andiamo nel file “HelloWorldViewController.m” e inseriamo, in un qualsiasi punto,<br />

questo metodo:<br />

1<br />

2<br />

3<br />

4<br />

-(BOOL)textFieldShouldReturn:(UITextField *)textField{<br />

! [textField resignFirstResponder];<br />

! return YES;<br />

}<br />

Questo metodo si occu<strong>per</strong>à della chiusura della nostra tastiera. Non soffermiamoci sul codice,<br />

in quanto è così in qualsiasi occasione voi vogliate implementarlo. Salvate entrambi i file e aprite<br />

“HelloWorldViewController.xib”. Cliccate sulla UITextField e aprite il “Connections Inspector”:<br />

vedrete nella sezione “Outlets” un elemento chiamato “delegate”, prendete il pallino e<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 25


trascinatelo sul “File’s Owner” nel pannello dei documenti. Se avrete eseguito correttamente<br />

questa o<strong>per</strong>azione il vostro pannello sarà come questo:<br />

In pratica, abbiamo detto che il delegato di tale oggetto è gestito dalla classe “HelloWorld-<br />

ViewController”.<br />

Salvate ora il tutto e chiudete Interface Builder. Provate poi ad eseguire la vostra applicazione,<br />

tutto funzionerà in maniera corretta!<br />

Avete così creato la vostra prima applicazione funzionante <strong>per</strong> <strong>iPhone</strong>!<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 26


Capitolo 4: TrashApp, gestiamo le immagini<br />

In questo secondo tutorial, inizieremo a prendere confidenza con un aspetto molto importante:<br />

la gestione delle immagini, e come l’utente può interagire con esse. Andremo a creare, infatti,<br />

un finto cestino, in cui potremo trascinare un’immagine e ripristinarla tramite un apposito<br />

pulsante.<br />

DEFINIAMO L’APPLICAZIONE<br />

Creiamo un nuovo progetto di tipo “View-Based Application” e chiamiamolo “TrashApp”. A<br />

differenza del tutorial precedente, questa volta creeremo tutto tramite Interface Builder, metodo<br />

sicuramente più veloce e comodo <strong>per</strong> applicazioni non troppo complesse.<br />

Prima di fare qualsiasi cosa, inseriamo nel nostro progetto le immagini che ci serviranno. Io<br />

utilizzerò le seguenti immagini: due <strong>per</strong> il cestino, e una <strong>per</strong> il documento da “eliminare” (potete<br />

trovare queste immagini nel file di progetto dell’esempio):<br />

TrashIconEmpty.png TrashIconFu".png windows icon.png<br />

Trascinate le immagini nel progetto in XCode, e nel pop-up che vi apparirà mettere la spunta a<br />

“Copy items into destination group’s folder (if needed)”. Noterete ora le immagini all’interno del progetto:<br />

Prima di definire la struttura grafica della nostra applicazione, andiamo a definire i componenti<br />

che poi ci serviranno. Apriamo il file “TrashAppViewController.h” e inseriamo le seguenti definizioni:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 27


1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

#import <br />

@interface TrashAppViewController : UIViewController {<br />

! IBOutlet UIImageView *imageCestino;<br />

! IBOutlet UIImageView *imageLogo;<br />

}<br />

-(IBAction)ripristina;<br />

@end<br />

Abbiamo definito gli elementi necessari: alle righe 4 e 5 due UIImageView, che conterranno il<br />

cestino (pieno o vuoto a seconda del caso) e il logo da eliminare. Alla riga 8, infine, abbiamo<br />

definito l’azione che ci <strong>per</strong>metterà di ripristinare il logo dopo la sua eliminazione.<br />

DEFINIAMO L’ASPETTO GRAFICO.<br />

Procediamo, quindi, con la creazione della struttura grafica della nostra applicazione. Salvate il<br />

file “TrashAppViewController.h” appena modificato e aprite poi<br />

“TrashAppViewController.xib”, che avvierà Interface Builder.<br />

La finestra è <strong>per</strong> ora semplice e si presenterà così:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 28


Inseriamo, <strong>per</strong> prima cosa, gli elementi necessari: due componenti UIImageView e un UIButton.<br />

Attenzione: la prima UIImageView che inserite deve essere quella in basso, altrimenti<br />

avrete problemi nelle fasi successive! Ecco come si presenterà la vostra applicazione:<br />

Ora dobbiamo collegare i vari componenti alle immagini che abbiamo inserito all’inizio del<br />

progetto. Clicchiamo sul primo componente UIImageView (quello più in alto, ma il secondo<br />

che avete inserito!) e apriamo il pannello “Attributes Inspector”. Nel menù a tendina “Image”<br />

selezioniamo il file “windows icon.png” e lo vedremo comparire anche nell’applicazione. Spuntiamo,<br />

inoltre, la casella “User Interaction Enabled”. Avremo un pannello così impostato:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 29


Facciamo la stessa cosa <strong>per</strong> la UIImageView sottostante, selezionando come immagine<br />

“TrashIconEmpty.png”, ma senza spuntare “User Interaction Enabled”. Inseriamo all’interno<br />

del bottone la scritta “Ripristina logo”, aggiustiamo le dimensioni e la posizione delle due immagini<br />

(in modo che i bordi delle UIImageView coincidano con le immagini al loro interno)<br />

fino ad avere un risultato come questo:<br />

Ora non dobbiamo fare alto che collegare gli elementi che abbiamo definito all’inizio di questo<br />

tutorial con i componenti all’interno della nostra applicazione.<br />

Dal Pannello dei Documenti selezioniamo il “File’s Owner”:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 30


Ora apriamo il “Connections Inspector”, dovremmo vedere i seguenti elementi:<br />

Prendiamo il pallino che troviamo a fianco di “imageLogo” e trasciniamolo sul logo di Windows,<br />

mentre quello di “imageCestino” sull’immagine del cestino.<br />

Colleghiamo, infine, l’azione: proprio come nello scorso tutorial, colleghiamo il pallino dell’azione<br />

“ripristina:” sul bottone, e nel menù che appare selezioniamo “Touch Up Inside”. Se<br />

abbiamo eseguito tutto in maniera corretta avremo un pannello come il seguente:<br />

Abbiamo concluso questa fase del tutorial. Salviamo tutto e chiudiamo pure Interface Builder.<br />

IMPLEMENTIAMO IL MOVIMENTO DEL LOGO<br />

Iniziamo aprendo il file “TrashAppViewController.h” e dichiarando un paio di elementi che ci<br />

serviranno:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 31


1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

#import <br />

@interface TrashAppViewController : UIViewController {<br />

! IBOutlet UIImageView *imageCestino;<br />

! IBOutlet UIImageView *imageLogo;<br />

!<br />

! BOOL cancellato;<br />

}<br />

-(IBAction)ripristina;<br />

-(void)cancella;<br />

Alla riga 7 abbiamo aggiunto una variabile che ci servirà <strong>per</strong> controllare se il nostro oggetto è<br />

già stato eliminato (quindi, al valore YES corrisponderà il logo eliminato, con NO il nostro logo<br />

sarà ancora visibile); lo stesso vale <strong>per</strong> il metodo “cancella”, che si occu<strong>per</strong>à invece dell’animazione<br />

legata all’eliminazione del logo.<br />

Ora iniziamo ad implementare i metodi necessari. Apriamo il file “TrashAppViewController.m”<br />

e inseriamo il seguente codice:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

12<br />

13<br />

14<br />

15<br />

16<br />

17<br />

18<br />

19<br />

20<br />

21<br />

22<br />

23<br />

24<br />

25<br />

26<br />

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {<br />

! UITouch *touch = [[event allTouches] anyObject];<br />

! if ([touch view] == imageLogo) {<br />

! ! imageLogo.center = [touch locationInView:self.view];!<br />

! }! !<br />

}<br />

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {<br />

! if (CGRectIntersectsRect([imageCestino frame], [imageLogo<br />

frame])){<br />

! ! imageCestino.image = [UIImage<br />

imageNamed:@"TrashIconFull.png"];<br />

! ! [self cancella];<br />

! } else{<br />

! ! [UIView beginAnimations:nil context:NULL];<br />

! ! [UIView setAnimationDuration:0.5];<br />

! ! imageLogo.center=CGPointMake(155.0,100.0);<br />

! ! [UIView commitAnimations];<br />

! }<br />

}<br />

- (void)cancella{<br />

! cancellato = YES;<br />

! [UIView beginAnimations:nil context:NULL];<br />

! [UIView setAnimationDuration:0.5];<br />

! imageLogo.transform = CGAffineTransformMakeScale(.001, .001);<br />

! [UIView commitAnimations];<br />

}<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 32


Abbiamo definito tre metodi, che si occu<strong>per</strong>anno del movimento del logo di Windows e della<br />

sua cancellazione. vediamoli nel dettaglio:<br />

• touchesMoved, (dalla riga 1 alla 6) In questo metodo, salviamo nella variabile “touch”<br />

l’evento che l’utente compie toccando un qualsiasi oggetto della nostra applicazione (riga<br />

2). Controlliamo, poi, che l’oggetto toccato corrisponda a “imageLogo” (riga 3), cioè al logo<br />

di Windows: se l’oggetto è proprio quello, teniamo traccia del centro dell’oggetto (che nel<br />

frattempo viene mosso dall’utente) con la posizione del dito sullo schermo (riga 4). Ovvero,<br />

è come se spostassimo fisicamente l’oggetto con il nostro dito e lo muovessimo su un piano.<br />

• touchesEnded, (dalla riga 8 alla 18) In questo metodo diciamo semplicemente che se il<br />

frame di “imageLogo” (ovvero il logo di Windows) interseca il frame del cestino (riga 9),<br />

deve essere chiamato il metodo “cancella”, che si occu<strong>per</strong>à dell’animazione della cancellazione<br />

(riga 11). Prima di chiamare tale metodo, inoltre, cambiamo l’immagine del cestino<br />

vuoto con quella del cestino pieno (riga 10). Se il logo, invece, non è stato spostato sopra il<br />

cestino, eseguiamo una semplice animazione, che riporta l’immagine al centro della vista<br />

(dalla riga 13 alla 16).<br />

• cancella, (dalla riga 20 alla 26) In questo metodo definiamo l’animazione che avrà il logo di<br />

Windows quando verrà sposato sopra il cestino. Alla riga 21 cambiamo il valore della variabile<br />

“cancella”, in modo da sa<strong>per</strong>e che il logo è stato eliminato. Alla riga 22 definiamo il<br />

punto di partenza della nostra animazione, mentre con l’istruzione successiva ne definiamo<br />

la durata. La riga 24 è l’animazione vera e propria, che farà scomparire il logo. Con l’ultima<br />

istruzione definiamo la fine dell’animazione.<br />

IL RIPRISTINO DEL LOGO<br />

Abbiamo quasi terminato la nostra applicazione, manca solo la definizione dell’azione “ripristina:”.<br />

Tale metodo è già stato definito da Interface Builder, quindi noi dobbiamo solo scrivere il<br />

codice al suo interno. Ecco le istruzioni da inserire:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

- (IBAction)ripristina{<br />

! if (cancellato) {<br />

! ! [UIView beginAnimations:nil context:NULL];<br />

! ! [UIView setAnimationDuration:0.5];<br />

! ! imageLogo.transform = CGAffineTransformIdentity;<br />

! ! imageCestino.image = [UIImage<br />

imageNamed:@"TrashIconEmpty.png"];<br />

! ! imageLogo.center = CGPointMake(155.0, 100.0);<br />

! ! [UIView commitAnimations];<br />

! ! cancellato = NO;<br />

! }<br />

}<br />

Questo metodo è speculare a “cancella”, in quanto dobbiamo eseguire l’animazione inversa!<br />

Andremo, quindi, ad eseguire un’animazione, che porterà il logo dal cestino (in cui si trova) alla<br />

posizione originale (o quasi, in quanto è definita in modo arbitrario da noi, alla riga 7).<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 33


Clicchiamo ora su “Build and Go!”, e testiamo la nostra applicazione funzionante!<br />

Nota: se non avete l’animazione, controllate che il logo di Windows non si nasconda dietro il<br />

cestino. Se così fosse, non avete seguito quello che vi ho detto nella costruzione dell’Interfaccia!!<br />

Ma non dis<strong>per</strong>ate, vi basterà entrare in Interface Builder, selezionare la UIImageView con<br />

il logo di Windows e dal menù “Layout” cliccare su “Send Forward” (in alternativa dovete<br />

scambiare l’ordine dei due componenti, ovviamente invertendo anche le immagini e le proprietà<br />

associate).<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 34


Capitolo 5: UIToolbar e auto-rotazione<br />

In questo terzo tutorial, analizzeremo un componente molto importante, la UIToolbar, e una<br />

funzionalità molto gradita agli utenti, l’auto-rotazione.<br />

Non creeremo nessuna applicazione complicata, semplicemente avremo due pulsanti nella<br />

toolbar che modificheranno il valore di una label posta al centro dello schermo. L’auto-rotazione,<br />

infine, aggiungerà un tocco più professionale alla nostra applicazione.<br />

DEFINIAMO L’APPLICAZIONE<br />

Come sempre, la prima cosa che faremo è definire un nuovo progetto. Creiamo un nuovo progetto<br />

di tipo “View-Based Application” e chiamiamolo “CountRotateApp”. Procediamo proprio<br />

come abbiamo fatto nello scorso tutorial, quindi apriamo il file<br />

“CountRotateAppViewController.h” e inseriamo le seguenti dichiarazioni:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

#import <br />

@interface CountRotateAppViewController : UIViewController {<br />

! IBOutlet UILabel *labelNumero;<br />

}<br />

-(IBAction)aggiungi;<br />

-(IBAction)sottrai;<br />

@end<br />

Abbiamo definito una label, che ospiterà un numero, che sarà incrementato o decrementato in<br />

base al pulsante che verrà premuto (ovviamente saranno le azioni “aggiungi” e “sottrai” che si<br />

occu<strong>per</strong>anno di questo compito).<br />

Salviamo il file appena modificato e facciamo doppio clic su<br />

“CountRotateAppViewController.xib”, in cui andremo a definire l’aspetto della nostra applicazione.<br />

DEFINIAMO L’ASPETTO GRAFICO<br />

Iniziamo inserendo nella parte bassa della vista una UIToolbar, con due UIBarButtonItem: in<br />

uno scrivete “-”, nell’altro “+”. Noterete che i due bottoni sono quasi attaccati. Noi vogliamo<br />

che siano ai due estremi, quindi tra di essi inseriamo un “Flexible Space Bar Button Item”, in<br />

modo che restino sempre separati. Ecco come si presenterà la vostra toolbar:<br />

Questo spazio flessibile ha una grossa utilità: non solo ci separa i due bottoni, ma ci <strong>per</strong>mette<br />

di non doverci occupare della giusta distanza tra essi, anche nel caso che ne aggiungessimo un<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 35


terzo. Inoltre esso ci <strong>per</strong>mette di tenere i due bottoni alle estremità della barra anche nel caso<br />

in cui ruotassimo la nostra applicazione. Come facciamo a testarlo? Semplice. Cliccate sulla<br />

freccia presente nel titolo della finestra della nostra applicazione:<br />

Vedrete che la schermata ruoterà!<br />

E come possiamo notare i due bottoni restano agli estremi della nostra barra. Proprio il risultato<br />

che volevamo!<br />

Riportiamo la finestra alla sua posizione originale, e inseriamo al centro una UILabel, partendo<br />

da un angolo in alto a sinistra, <strong>per</strong> poi ingrandirla fino all’angolo opposto. Nell’Attribute Inspector<br />

settate i seguenti parametri:<br />

• “Text”: 0 (zero);<br />

• A"ineamento centrale;<br />

• “Font Size”: 200<br />

Dovreste avere il seguente risultato:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 36


Proviamo ora a far ruotare la schermata come abbiamo fatto poco fa. Noteremo che lo zero<br />

non rimane in posizione centrale, ma addirittura viene <strong>per</strong> metà nascosto. Come facciamo a<br />

lasciarlo centrato? Anche qui ci viene in aiuto l’Interface Builder, che offre grandi potenzialità<br />

anche in questo aspetto.<br />

Selezioniamo la label che contiene lo zero e apriamo il “Size Inspector”. Nella seconda parte<br />

possiamo vedere che vi è una sezione denominata “Autosizing”. Clicchiamo sulle due freccette<br />

rosse che vediamo nel riquadro piccolo, in modo da avere questo schema:<br />

Proviamo ora a ruotare la nostra applicazione: lo zero resterà <strong>per</strong>fettamente in posizione centrale!<br />

Ora che abbiamo definito la struttura grafica dell’applicazione, non ci resta altro che collegare<br />

l’elemento e le due azioni che abbiamo definito all’inizio del tutorial.<br />

Dal Pannello dei Documenti selezioniamo il File’s Owner e spostiamoci poi nel “Controller<br />

Connections” (come abbiamo già fatto nel capitolo 4). Dovete avere un pannello come questo:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 37


Colleghiamo “labelNumero” con l’unica label presente al centro della vista, e le due azioni ai<br />

rispettivi bottoni (al bottone “+” l’azione “aggiungi”, mentre al bottone “-” l’azione “sottrai”).<br />

Se avete eseguito tutto in maniera corretta avrete questo risultato:<br />

Salviamo tutto e chiudiamo Interface Builder.<br />

SCRIVIAMO IL CODICE NECESSARIO<br />

Prima di iniziare ad implementare i metodi che abbiamo già definito, aggiungete questa variabile<br />

al file “CountRotateAppViewController.h”:<br />

1<br />

2<br />

3<br />

4<br />

@interface CountRotateAppViewController : UIViewController {<br />

! IBOutlet UILabel *labelNumero;<br />

! int numero;<br />

}<br />

Semplicemente, abbiamo definito una variabile intera alla riga 3, di nome “numero”, che conterrà<br />

il valore mostrato dalla label.<br />

Passiamo, quindi, al file “CountRotateAppViewController.m”.<br />

Iniziamo con questo semplice metodo (dovreste trovarlo già presente nella classe, vi basterà<br />

eliminare i commenti che lo rendono nascosto):<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 38


1<br />

2<br />

3<br />

4<br />

- (void)viewDidLoad {<br />

! [su<strong>per</strong> viewDidLoad];<br />

! numero = 0;<br />

}<br />

Questo metodo viene richiamato sempre all’avvio del file “.xib” associato alla classe (i file “.xib”<br />

sono quelli creati da InterfaceBuilder). In questo metodo possiamo inizializzare tutti i componenti<br />

che ci serviranno. Qui, in pratica, dobbiamo inserire tutte quelle o<strong>per</strong>azioni che vogliamo<br />

vengano eseguite all’avvio dell’applicazione. Nel nostro esempio, vogliamo che la variabile<br />

“numero” sia impostata a zero. Prendete confidenza con tale metodo <strong>per</strong>chè lo incontrerete<br />

spesso nei prossimo tutorial.<br />

Aggiungiamo, ora, le implementazioni <strong>per</strong> i due metodi che si occupano di aumentare e diminuire<br />

il valore della variabile “numero”:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

- (IBAction)aggiungi {<br />

! numero++;<br />

! labelNumero.text = [[NSString alloc]<br />

initWithFormat:@"%i",numero];<br />

}<br />

- (IBAction)sottrai {<br />

numero--;<br />

! labelNumero.text = [[NSString alloc]<br />

initWithFormat:@"%i",numero];<br />

}<br />

Questo due metodi non eseguono niente di complesso, si limitano a incrementare (o decrementare)<br />

la variabile “numero”, <strong>per</strong> poi visualizzarla nella label. Semplice vero?<br />

L’ultima cosa da implementare è la rotazione della vista. Sempre nel file<br />

“CountRotateAppViewController.m” cercate e decommentate il seguente metodo (è già presente,<br />

vi basterà decommentarlo e modificare l’istruzione alla riga 3):<br />

1<br />

2<br />

3<br />

4<br />

-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientatio<br />

n)interfaceOrientation {<br />

// Return YES for supported orientations<br />

return YES;<br />

}<br />

Questo è un metodo della classe “UIViewController”, che implementa già la rotazione automatica<br />

dello schermo. Ancora una volta non dovremo fare veramente niente, in quanto sono le<br />

librerie del <strong>SDK</strong> a fornirci tutti pronto.<br />

Piccola nota: se non volessimo implementare l’auto-rotazione, ci basterebbe ritornare come<br />

valore “NO”, oppure semplicemente non inserire il metodo nell’applicazione.<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 39


Clicchiamo ora su “Build and Go!” e testiamo la nostra applicazione!<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 40


Capitolo: 6: NSTimer e UIProgressView<br />

Proseguiamo la panoramica sui componenti più utilizzati nella creazione di applicazioni <strong>per</strong><br />

<strong>iPhone</strong>. In questo capitolo vedremo come utilizzare la classe NSTimer, ovvero un temporizzatore,<br />

che ci <strong>per</strong>metterà di eseguire animazioni e transizioni con durate predefinite. Utilizzeremo,<br />

inoltre, la UIProgressView, ovvero la barra di progresso, necessaria quando si deve mostrare<br />

un caricamento.<br />

Quella che andremo a creare sarà una semplice applicazione, che <strong>per</strong>metterà all’utente di cambiare<br />

il colore dello sfondo, semplicemente cliccando su un bottone. Il cambio del colore, inoltre,<br />

avverrà in maniera graduale tramite un’animazione della durata di 10 secondi.<br />

DEFINIAMO L’APPLICAZIONE<br />

Come sempre, iniziamo creando un progetto di tipo “View-Based Application” e chiamiamolo<br />

“ProgressColour”.<br />

Apriamo il file “ProgressColourViewController.h” e definiamo i seguenti componenti:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

12<br />

13<br />

#import <br />

@interface ProgressColourViewController : UIViewController {<br />

! IBOutlet UILabel *progressLabel;<br />

! IBOutlet UIProgressView *progressBar;<br />

!<br />

! IBOutlet UIButton *bottoneBlu;<br />

! IBOutlet UIButton *bottoneRosso;<br />

}<br />

- (IBAction)caricamentoColore:(id)bottone;<br />

@end<br />

La label definita alla riga 4 servirà <strong>per</strong> mostrare un messaggio all’utente sul grado di completamento<br />

dell’animazione, mentre la UIProgressBar darà la stessa informazioni ma in maniera più<br />

visiva (è una classica barra di caricamento). Abbiamo, inoltre, dichiarato anche due bottoni<br />

UIButton: vedremo, poi, il <strong>per</strong>chè di questa dichiarazione.<br />

L’azione alla riga 11 verrà associata ad entrambi i bottoni, infatti sarà questo metodo ad avviare<br />

il cambio di colore dello sfondo. Nell’intestazione di questo metodo c’è anche un parametro<br />

“bottone” di tipo “id”: questo ci servirà <strong>per</strong> determinare quale bottone ha invocato il metodo,<br />

in modo da poter caricare il colore scelto dall’utente.<br />

Possiamo ora iniziare a definire l’aspetto grafico dell’applicazione, aprendo il file<br />

“ProgressColourViewController.xib”.<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 41


DEFINIAMO L’ASPETTO GRAFICO<br />

Inseriamo nella nostra vista i primi due componenti necessari: una UILabel e una UIProgressView.<br />

Ricreate una disposizione simile a questa (ovviamente nessuno vi vieta di <strong>per</strong>sonalizzarla<br />

a vostro piacimento):<br />

Come potete notare la label e la barra di progresso occupano quasi <strong>per</strong> intero la larghezza della<br />

vista, questo <strong>per</strong> rendere più evidente ciò che avviene.<br />

Selezioniamo la label e apriamo “Attributes Inspector”, <strong>per</strong> modificare alcune proprietà:<br />

• cancellate il contenuto del campo “Text”;<br />

• “Font Size”: 20<br />

• allineamento centrale.<br />

Selezioniamo ora la UIProgressView e, sempre in “Attributes Inspector”, impostiamo il valore<br />

della casella “Progress” a zero.<br />

Inseriamo ora nella vista due bottoni, in modo da avere un risultato finale come questo:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 42


Abbiamo già concluso la creazione della parte grafica della nostra applicazione. Non ci resta<br />

che collegare i componenti che abbiamo definito ad inizio tutorial.<br />

Dal Pannello dei Documenti selezioniamo, come sempre, il “File’s Owner” e apriamo il “Connections<br />

Inspector”. Dovreste avere un pannello così composto:<br />

Colleghiamo l’elemento “progressLabel” con la label vuota presente sopra la barra, e “progressBar”<br />

con la barra stessa. Colleghiamo anche gli elementi “bottoneBlu” e “bottoneRosso”<br />

con i due relativi pulsanti. Colleghiamo, infine, l’azione “caricamentoColore” con entrambi i<br />

bottoni, selezionando “Touch Up Inside” dal menù a tendina che si presenta. Se avete eseguito<br />

tutto in maniera corretta dovreste avere questo risultato:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 43


Abbiamo così terminato questa fase. Salviamo e chiudiamo Interface Builder.<br />

SCRIVIAMO IL CODICE<br />

Dobbiamo definire due elementi e un paio di metodi che non abbiamo scritto inizialmente.<br />

Apriamo il file “ProgressColourViewController.h” e inserite le dichiarazioni mancanti:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

12<br />

13<br />

14<br />

15<br />

16<br />

17<br />

18<br />

19<br />

20<br />

21<br />

#import <br />

@interface ProgressColourViewController : UIViewController {<br />

! IBOutlet UILabel *progressLabel;<br />

! IBOutlet UIProgressView *progressBar;<br />

!<br />

! IBOutlet UIButton *bottoneBlu;<br />

! IBOutlet UIButton *bottoneRosso;<br />

!<br />

! NSTimer *timer;<br />

! UIColor *colore;<br />

}<br />

@pro<strong>per</strong>ty (nonatomic, retain) NSTimer *timer;<br />

@pro<strong>per</strong>ty (nonatomic, retain) UIColor *colore;<br />

- (IBAction)caricamentoColore:(id)bottone;<br />

- (void)aggiornaColore ;<br />

- (void)applicaColore ;<br />

@end<br />

Abbiamo definito un componente “NSTimer” (alla riga 10), che sarà il temporizzatore che ci<br />

<strong>per</strong>metterà di eseguire l’animazione prevista. Nella riga successiva è definito un elemento UI-<br />

Color, che servirà <strong>per</strong> tener traccia del colore che deve essere applicato allo sfondo.<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 44


Sono stati dichiarati, inoltre, due nuovi metodi, che ci serviranno <strong>per</strong> implementare le azioni<br />

necessarie (righe 18 e 19).<br />

Passiamo ora al file “ProgressColourViewController.m” e iniziamo ad implementare i metodi<br />

necessari. Inseriamo il seguente codice:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

12<br />

13<br />

14<br />

15<br />

16<br />

17<br />

18<br />

19<br />

#import "ProgressColourViewController.h"<br />

@implementation ProgressColourViewController<br />

@synthesize timer;<br />

@synthesize colore;<br />

- (IBAction)caricamentoColore:(id)bottone {<br />

! progressBar.progress = 0.0;<br />

! if (bottone == bottoneBlu){<br />

! ! progressLabel.text = @"Caricamento colore blu...";<br />

! ! colore = [UIColor blueColor];<br />

! }else if (bottone == bottoneRosso) {<br />

! ! progressLabel.text = @"Caricamento colore rosso...";<br />

! ! colore = [UIColor redColor];<br />

! }<br />

! timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self<br />

selector:@selector(aggiornaColore) userInfo:nil repeats:YES];<br />

}<br />

Questo metodo si occupa di avviare il caricamento del colore scelto dall’utente. Alla riga 9 viene<br />

settato il valore di progresso della barra a zero (tale valore di default va da 0.0 a 1.0, ma questo<br />

intervallo può essere modificato a piacere). Troviamo, poi, un controllo sul bottone che ha<br />

invocato il metodo (riga 10): se il bottone premuto dall’utente è quello <strong>per</strong> il colore blu, impostiamo<br />

la label indicando che viene caricato il blu, e assegniamo alla variabile “colore” il valore<br />

“[UIColor blueColor]”. Questo è un elemento predefinito della classe UIColor, che ci <strong>per</strong>mette<br />

di utilizzare colori standard in maniera semplice e veloce. Nello stesso modo lavora la clausola<br />

“else if”, ovviamente controllando se il bottone premuto è quello <strong>per</strong> il colore rosso.<br />

Alla riga 17, infine, viene definita la variabile timer, istanziandola con la classe NSTimer. Ci sono<br />

tre parametri molto importanti in questa funzione: la durata di 1 secondo (alla clausola<br />

“scheduledTimerWithTimeInterval”), il metodo che deve essere eseguito ad ogni ripetizione<br />

(clausola “@selector()”) e la ripetizione continua di tale intervallo di tempo (impostata tramite<br />

“repeats:YES“).<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 45


Proseguiamo con la definizione dei metodi:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

- (void)aggiornaColore {<br />

! progressBar.progress = progressBar.progress + 0.1;<br />

! if (progressBar.progress == 0.5){<br />

! ! progressLabel.text = @"Applicando colore…";<br />

! ! [self applicaColore];<br />

! }<br />

! if (progressBar.progress == 1.0){<br />

! ! progressLabel.text = @"Colore applicato!";<br />

! ! [timer invalidate];<br />

! }<br />

}<br />

Alla riga 2 incrementiamo il valore della nostra barra di progresso, aumentandone il valore del<br />

10%. Alla riga 3 troviamo un controllo if, che verifica se il valore della barra è 0.5 (ovvero siamo<br />

a metà): in caso affermativo, cambiamo il testo presente nella label, altrimenti lasciamo tutto<br />

invariato. Anche alla riga 7 un ciclo if controlla se la barra di progresso è arrivata al suo valore<br />

massimo: in tal caso inseriamo un nuovo testo nella label, e fermiamo il timer (con l’istruzione<br />

alla riga 9).<br />

Nel primo ciclo if che abbiamo esaminato, notiamo che alla riga 5 viene richiamato il metodo<br />

“applicaColore”: tale metodo avrà il compito di cambiare il colore allo sfondo della vista, con<br />

un’animazione che dovrà durare 5 secondi (infatti siamo al 50% del progresso, e la barra avanza<br />

del 10% ogni secondo). Ecco tale metodo:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

- (void)applicaColore {<br />

! [UIView beginAnimations:nil context:NULL];<br />

! [UIView setAnimationDuration:5.0];<br />

! self.view.backgroundColor = colore;<br />

! [UIView commitAnimations];<br />

}<br />

In questi due metodi viene definita l’animazione che <strong>per</strong>mette allo sfondo della nostra vista di<br />

cambiare colore. L’animazione rispecchia molto quella illustrata in un capitolo precedente.<br />

Alla riga 3 definiamo la durata di tale animazione (5 secondi); l’istruzione successiva è il risultato<br />

che vogliamo ottenere, ovvero il nostro colore di sfondo. Chiude il gruppo di istruzioni la<br />

riga 5, che avvia l’animazione.<br />

Clicchiamo su “Build and Go!” e testiamo la nostra applicazione!<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 46


<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 47


Capitolo 7: AccessContact, accediamo alla rubrica<br />

In questo capitolo andremo ad implementare una funzione un po’ particolare, in quanto accederemo<br />

all’applicazione nativa “Contatti” e ricaveremo le informazioni di un contatto.<br />

Impareremo ad utilizzare il framework (una sorta di libreria, che ci fornisce delle funzionalità<br />

già pronte) “AddressBook” e come sfruttare le funzioni che ci mette a disposizione.<br />

DEFINIAMO IL PROGETTO<br />

Iniziamo creando un progetto del tipo “View-Based Application” e chiamiamolo “AccessContact”.<br />

Questa volta procederemo come nel primo tutorial, ovvero andremo a definire prima i<br />

componenti via codice, poi li collegheremo tramite Interface Builder.<br />

Apriamo il file “AccessContactViewController.h”, che è la classe della vista che ci viene fornita<br />

con questo template. Inseriamo il seguente codice:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

12<br />

13<br />

#import <br />

#import <br />

#import <br />

@interface AccessContactViewController : UIViewController {<br />

! IBOutlet UILabel *labelNome;<br />

! IBOutlet UILabel *labelCognome;<br />

! IBOutlet UILabel *labelTel;<br />

}<br />

- (IBAction)getContatto;<br />

@end<br />

Ormai siete es<strong>per</strong>ti, e avrete subito capito che abbiamo definito tre label e un’azione. Alle righe<br />

2 e 3, <strong>per</strong>ò, abbiamo importato due librerie, che si riferiscono ad “AddressBook”, ovvero all’applicazione<br />

“Contatti”. Questo, <strong>per</strong>ò, non basta <strong>per</strong> poter utilizzare tutte le sue funzioni. Dobbiamo<br />

importare all’interno del nostro progetto anche il framework necessario.<br />

Espandete la sezione “Targets” nel progetto, e cliccate con il tasto destro su “AccessContact”,<br />

selezionando poi “<strong>Get</strong> Info”. Si aprirà una nuova schermata, in cui dobbiamo andare nella sezione<br />

“General”. Nell’angolo in basso a sinistra noteremo un bottone “+”, clicchiamo e si aprirà<br />

un elenco di tutti i framework disponibili:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 48


Selezioniamo “AddressBook.framework” e “AddressBookUI.framework” e clicchiamo poi su<br />

“Add”. Avremo così aggiunto questi due framework al nostro progetto. Possiamo così chiudere<br />

la schermata delle proprietà.<br />

Salviamo il file “AccessContactViewController.h” e facciamo doppio clic su<br />

“AccessContactViewControlle.xib” <strong>per</strong> aprire Interface Builder.<br />

DEFINIAMO LA STRUTTURA GRAFICA<br />

Dobbiamo ora definire l’aspetto grafico della nostra applicazione. Inseriamo le label necessarie<br />

e un bottone, <strong>per</strong> ricreare un aspetto grafico come questo:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 49


Le label con il testo “---” sono quelle che poi conterranno le informazioni sul contatto selezionato<br />

dall’utente. Dobbiamo ora collegare gli elementi definiti in precedenza con quelli che abbiamo<br />

appena inserito nella vista.<br />

Tramite il pannello dei documenti selezioniamo “File’s Owner”, e apriamo il “Connections Inspector”.<br />

Potremo vedere i componenti che abbiamo dichiarato:<br />

Ora dobbiamo collegarli nella maniera corretta, ovviamente in base al nome con cui li abbiamo<br />

chiamati: “labelNome”, quindi, andrà collegata con la label a fianco di “Nome” e così via.<br />

L’azione “getContatto”, invece, sarà da collegare al bottone, scegliendo come sempre “Touch<br />

Up Inside” tra le azioni disponibili. Ecco il risultato finale dei collegamenti:<br />

Possiamo salvare tutto e chiudere Interface Builder.<br />

SCRIVIAMO IL CODICE NECESSARIO<br />

Dobbiamo ora implementare i metodi necessari <strong>per</strong> far funzionare l’applicazione. Iniziamo con<br />

la definizione del metodo “getContatto”, ovvero l’azione collegata alla pressione del bottone.<br />

Apriamo il file “AccessContactViewController.m” e inseriamo il seguente codice:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 50


1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

-(IBAction)getContatto {<br />

! //Crea l’oggetto necessario<br />

! ABPeoplePickerNavigationController *picker = [[ABPeoplePickerNavigationController<br />

alloc] init];<br />

! //Il delegato dell’oggetto è definito nella classe stessa<br />

! picker.peoplePickerDelegate = self;<br />

! //Visualizza l’app Contatti<br />

! [self presentModalViewController:picker animated:YES];<br />

! //Rilascia l’oggetto<br />

! [picker release];<br />

}<br />

Come si può leggere dai commenti, questo metodo istanzia un oggetto chiamato “picker”, che<br />

ci <strong>per</strong>metterà di aprire l’applicazione nativa “Contatti”. Alla riga 5 definiamo il delegato di tale<br />

oggetto: impostando “self”, comunichiamo che sarà la stessa classe (ovvero “AccessCon-<br />

tactViewController”) a definire gli altri metodi necessari, che definiremo tra poco. Alla riga 7,<br />

infine, inseriamo tale oggetto come vista principale della nostra applicazione: l’utente vedrà<br />

così comparire l’applicazione nativa “Contatti” all’interno della nostra applicazione “AccessContact”.<br />

Dobbiamo ora implementare i metodi richiesti dal delegato. Ecco il codice da inserire:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

12<br />

13<br />

14<br />

15<br />

16<br />

17<br />

18<br />

- (BOOL)peoplePickerNavigationController: (ABPeoplePickerNavigation-<br />

Controller *)peoplePicker<br />

shouldContinueAfterSelectingPerson:(ABRecordRef)<strong>per</strong>son {<br />

! //Settiamo il nome<br />

labelNome.text = (NSString *)ABRecordCopyValue(<strong>per</strong>son, kABPersonFirstNamePro<strong>per</strong>ty);<br />

! //Settiamo il cognome<br />

labelCognome.text = (NSString *)ABRecordCopyValue(<strong>per</strong>son,<br />

kABPersonLastNamePro<strong>per</strong>ty);!<br />

! //Settiamo il numero di telefono<br />

! ABMultiValueRef multi = ABRecordCopyValue(<strong>per</strong>son, kABPersonPhone-<br />

Pro<strong>per</strong>ty);<br />

! labelTel.text = (NSString*)ABMultiValueCopyValueAtIndex(multi,<br />

0);<br />

! //Rimuove il controller "Contatti"<br />

[self dismissModalViewControllerAnimated:YES];!<br />

return NO;<br />

}<br />

-<br />

(void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavig<br />

ationController *)peoplePicker {<br />

// facciamo tornare il controller alla vista principale<br />

! [self dismissModalViewControllerAnimated:YES];<br />

}<br />

Il primo metodo legge le informazioni del contatto selezionato, e le setta nelle apposite label.<br />

L’unico inconveniente è dato dalle righe 7 e 8, che si occupano della lettura del numero di tele-<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 51


fono: viene letto il primo numero presente (in quanto potrebbero anche esserci più numeri). E<br />

se non vi fosse nessun numero associato al contatto? In tal caso l’applicazione crasha. Questo<br />

avviene <strong>per</strong>ché non abbiamo effettuato nessun controllo, ma potete semplicemente risolvere<br />

questo problema tramite un opportuno ciclo if.<br />

Il metodo che inizia alla riga 15, infine, si occupa di chiudere l’applicazione “Contatti” quando<br />

l’utente sceglie di uscire senza selezionare nessun contatto (ovvero quando clicca su “Cancel”).<br />

Potete notare che l’istruzione di tale metodo è uguale a quella presente alla riga 10, che è uguale<br />

a sua volta a quella presente alla riga 7 del primo metodo implementato.<br />

Cliccate su “Build and Go!” e testate la vostra applicazione!<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 52


Capitolo 8: Creiamo un mini browser con le UIWebView<br />

Una delle caratteristiche principali dell’<strong>iPhone</strong> è la sua connettività, sia essa tramite WiFi, 3G o<br />

EDGE. Internet, quindi, ricopre un ruolo fondamentale nell’utilizzo di questo dispositivo. Ecco<br />

che sorge spesso necessario implementare una sorta di browser nelle nostre applicazioni, <strong>per</strong><br />

poter visualizzare delle pagine web. Anche in questo l’<strong>SDK</strong> si rivela molto potente, in quanto ci<br />

mette a disposizione un componente praticamente già pronto: le UIWebView. Questo componente<br />

è una sorta di “Safari lite”, in quanto ci <strong>per</strong>mette di visualizzare pagine web tramite lo<br />

stesso motore che è alla base di Safari.<br />

Nel tutorial vedremo come utilizzare le UIWebView, <strong>per</strong> realizzare un nostro mini-browser,<br />

con tre semplici pulsanti: avanti, indietro e ricarica. Certo, non potremo competere con Safari,<br />

ma potrebbe tornarvi molto utile nei vostri programmi.<br />

CREIAMO LA STRUTTURA GRAFICA<br />

Iniziamo creando un nuovo progetto di tipo “View-Based Application” e chiamiamolo “My-<br />

Browser”. Prima di definire l’aspetto della nostra applicazione, dichiariamo un componente che<br />

ci servirà (sarà il componente principale che caricherà le pagine web).<br />

Apriamo il file “MyBrowserViewController.h” e inseriamo la seguente definizione:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

@interface MyBrowserViewController : UIViewController {<br />

IBOutlet UIWebView *webView;<br />

}<br />

@end<br />

Salviamo il file e apriamo “MyBrowserViewController.xib” <strong>per</strong> avviare Interface Builder.<br />

Il template che abbiamo utilizzato ci fornisce già una vista di base, noi iniziamo inserendo nella<br />

parte bassa della vista un componente di tipo UIToolbar e tre bottoni (UIBarButtonItem,<br />

quelli utilizzati nel capitolo 5), separando gli ultimi due tramite un “Flexible Space” (anche questo<br />

già visto). I primi due bottoni ci serviranno <strong>per</strong> muoverci tra le pagine visitate (i classici<br />

“Avanti” e “Indietro”), mentre il terzo servirà a ricaricare la pagina. Ecco come appare la barra<br />

appena definita:<br />

Ora dobbiamo inserire la WebView. Dalla libreria scegliamo un componente “UIWebView” e<br />

inseriamolo nella nostra finestra. Ecco il risultato finale:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 53


DEFINIAMO I COMPONENTI E COLLEGHIAMO LE AZIONI<br />

Abbiamo già concluso con la definizione dell’interfaccia grafica. Dobbiamo ora definire i componenti<br />

che ci serviranno e collegare le relative azioni. Vedrete che si rivelerà tutto molto semplice,<br />

in quanto troveremo già tutto pronto.<br />

Iniziamo cliccando sul “File’s Owner” (che troviamo nel Pannello dei documenti). Colleghiamo<br />

il componente “webView” (che è quello definito all’inizio del tutorial) con la UIWebView che<br />

abbiamo appena inserito nella nostra applicazione. Se abbiamo eseguito questo passaggio correttamente<br />

avremo un pannello “Connections Inspector” come questo:<br />

Dopo aver fatto questo semplice collegamento, andiamo ancora nel Pannello dei documenti ed<br />

espandiamo il componente View e selezioniamo la UIWebView :<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 54


Andiamo nel “Connections Inspector” e noteremo che ci sono già delle azioni definite (“go-<br />

Back”, “goForward”, etc.), non dovremo far altro che collegarle con i bottoni adeguati. Ecco le<br />

associazioni da fare:<br />

• “goBack” con il bottone “”, ovvero <strong>per</strong> andare alla pagina successiva (della cronologia);<br />

• “reload” con il bottone “Ricarica”, <strong>per</strong> ricaricare la pagina web.<br />

Se avete eseguito tutto correttamente avrete un risultato come questo:<br />

Tutto molto semplice e veloce!<br />

Salviamo tutto e chiudiamo Interface Builder.<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 55


SCRIVIAMO IL CODICE PER APRIRE LA PAGINA DESIDERATA<br />

Dobbiamo ora inserire il codice che si occupa di caricare la pagina web desiderata e mostrarla<br />

nella UIWebView. Utilizziamo un metodo che viene caricato all’avvio dell’applicazione, e che ci<br />

<strong>per</strong>mette di settare i comportamenti iniziali del nostro browser.<br />

Aprite il file “MyBrowserViewController.m” e inserite il seguente codice:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

- (void)viewDidLoad{<br />

! //indirizzo web da caricare<br />

! NSString *indirizzo = @"http://www.bubidevs.net";<br />

! //crea un oggetto URL<br />

! NSURL *url = [NSURL URLWithString:indirizzo];<br />

! NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];<br />

! // visualizza la pagina nella UIWebView<br />

! [webView loadRequest:requestObj];<br />

}<br />

Come potete vedere si tratta solo di quattro istruzioni!<br />

Definiamo, alla riga 3, l’indirizzo che vogliamo aprire, mentre alle righe 5 e 6 inizializiamo i<br />

componenti necessari <strong>per</strong> poter visualizzare la pagina (non preoccupatevi troppo, sono sempre<br />

questi da utilizzare). All’istruzione 8, infine, settiamo i componenti che abbiamo appena creato<br />

nella UIWebView, in modo che venga mostrata la pagina web all’utente.<br />

E se volessimo caricare dei file HTML che abbiamo in locale? Semplice, modificate così le<br />

istruzioni alle righe 3 e 5:<br />

2<br />

3<br />

4<br />

5<br />

! //indirizzo web da caricare!<br />

! NSString *indirizzo = [[NSBundle mainBundle]<br />

pathForResource:@"index" ofType:@"html"];<br />

! //crea un oggetto URL<br />

! NSURL *url = [NSURL fileURLWithPath:indirizzo];<br />

in questo modo caricherà il file "index.html" che si deve trovare, <strong>per</strong>ò, nella stessa cartella in<br />

cui viene seguita l’applicazione (quindi dovete prima importarla nel vostro progetto). Semplice<br />

vero?<br />

Cliccate su “Build and Go!” e provate il vostro <strong>per</strong>sonalissimo browser!<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 56


<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 57


Capitolo 9: UITableView, gestiamo le tabelle<br />

Fino ad ora abbiamo analizzato dei componenti base, molto semplici sia da impostare che da<br />

utilizzare. Il componente più utilizzato, <strong>per</strong>ò, è sicuramente quello che gestisce le tabelle, ovvero<br />

la UITableView. In moltissime applicazioni, infatti, esse vengono utilizzate <strong>per</strong> mostrare<br />

delle informazioni all’utente, che può anche interagire con questi dati.<br />

In questo capitolo vedremo come definire una tabella, come inserire al suo interno dei valori e<br />

come definire dei comportamenti (ad esempio la cancellazione delle righe), necessari <strong>per</strong> renderla<br />

utilizzabile dall’utente.<br />

Questo capitolo è suddiviso in tre parti:<br />

1.Creazione e definizione de"a tabe"a;<br />

2.Inserimento di alcune funzionalità;<br />

3.Implementazione de"a ricerca.<br />

Analizzeremo queste parti una alla volta, passo <strong>per</strong> passo, in modo da comprendere bene ogni<br />

singola cosa che andremo a realizzare.<br />

PARTE 1: CREIAMO E DEFINIAMO LA TABELLA<br />

La prima parte di questo tutorial è dedicata alla creazione della struttura dell’applicazione: ne<br />

definiremo la grafica, la lista degli elementi da visualizzare e come mostrarli all’interno delle<br />

celle. Il tutto sarà fatto con la solita semplicità, sfruttando tutte le caratteristiche che XCode e<br />

l’<strong>SDK</strong> ci mettono a disposizione, semplificando il nostro lavoro.<br />

CREIAMO UN NUOVO PROGETTO<br />

Aprimo Xcode, selezioniamo “File -> New Project”. Nel menù che ci appare selezioniamo “Navigation-based<br />

Application”, clicchiamo su “Choose…” e immettiamo come nome “tableView<strong>Tutorial</strong>”<br />

e fate clic su “Save”. Abbiamo così creato il nostro nuovo progetto.<br />

Questo template di XCode ci fornisce già una tabella con una barra di navigazione, semplificandoci<br />

notevolmente il lavoro!<br />

Nota: questo tutorial funziona con <strong>SDK</strong> 3.0 e su<strong>per</strong>iori.<br />

Aprendo il file "RootViewController.xib" con Interface Builder possiamo notare la struttura già<br />

pronta, non dovremo toccare niente!<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 58


INSERIAMO IL CODICE NECESSARIO<br />

A differenza di tutti i passaggi che dovevano essere eseguiti fino al <strong>SDK</strong> 2.x, dovremo solamente<br />

inserire poche righe di codice <strong>per</strong> avere la nostra tabella già pronta e funzionante!<br />

Apriamo il file "RootViewController.h" e inseriamo la dichiarazione del seguente componente:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

@interface RootViewController : UITableViewController {<br />

! NSMutableArray *lista;<br />

}<br />

@pro<strong>per</strong>ty (nonatomic, retain) NSMutableArray *lista;<br />

@end<br />

Abbiamo definito un array in cui inseriamo tutti gli elementi che devono poi essere visualizzati<br />

nella tabella. Notate che abbiamo utilizzato un NSMutableArray, questo <strong>per</strong>ché dovremo avere<br />

la possibilità di poter modificare gli elementi che lo compongono (analizzeremo meglio questo<br />

aspetto quando sarà necessario).<br />

Spostiamoci ora nel file “RootViewController.m” e iniziamo inserendo queste istruzioni:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 59


1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

12<br />

13<br />

14<br />

15<br />

16<br />

17<br />

#import "RootViewController.h"<br />

@implementation RootViewController<br />

@synthesize lista;<br />

- (void)viewDidLoad {<br />

[su<strong>per</strong> viewDidLoad];<br />

!<br />

! self.title = @"Prodotti Apple";<br />

!<br />

! //elementi da visualizzare nella tabella<br />

! ! lista = [[NSMutableArray alloc] initWithObjects: @"<strong>iPhone</strong>",<br />

@"iPod",@"iPod Touch", @"iMac", @"iBook", @"MacBook", @"MacBook<br />

Pro", @"Mac Pro", @"PowerBook", nil];!<br />

// Uncomment the following line to display an Edit button in the<br />

navigation bar for this view controller.<br />

// self.navigationItem.rightBarButtonItem = self.editButtonItem;<br />

}<br />

Analizziamo quello che abbiamo appena scritto. Chi ha già un pochino di es<strong>per</strong>ienza con la<br />

programmazione <strong>per</strong> <strong>iPhone</strong> conoscerà certamente il metodo “viewDidLoad“: questo viene<br />

eseguito subito dopo il caricamento della vista, e ci <strong>per</strong>mette di settare tutte le variabili e tutti i<br />

parametri all’avvio. Per prima cosa abbiamo impostato il titolo alla nostra tabella, che apparirà<br />

nella NavigationBar presente nella vista (riga 10). Subito dopo viene inizializzata la lista (che è<br />

un oggetto NSMutableArray), inserendoci alcuni elementi (riga 13).<br />

Per ora non fate caso alle righe 15 e 16, ci saranno utili nella seconda parte del tutorial.<br />

Ora dobbiamo definire i metodi che si occupano di popolare la tabella. Scorrendo il file<br />

“RootViewController.m” li troverete già (XCode li inserisce sempre di default), dovete solo<br />

completarli. Iniziamo definendo i seguenti due:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {<br />

return 1;<br />

}<br />

// Setta il numero di righe della tabella .<br />

- (NSInteger)tableView:(UITableView *)tableView<br />

numberOfRowsInSection:(NSInteger)section {<br />

return [lista count];<br />

}<br />

Il primo metodo che incontriamo è “numberOfSectionsInTableView“. Se provate a modificare<br />

questo valore, vedrete che (quando eseguirete l’applicazione) la lista degli oggetti sarà ripetuta<br />

più volte. Provare <strong>per</strong> credere! A cosa serve? Nel caso in cui vogliate creare una tabella suddivi-<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 60


sa in più sezioni, ad esempio come quella dell’applicazione nativa “Contatti”, che suddivide gli<br />

elementi in ordine alfabetico.<br />

Il secondo è “numberOfRowInSection“, e setta il numero di celle in ogni sezione (nel nostro<br />

esempio avremo una sola sezione). Questo valore deve corrispondere al numero di elementi che<br />

vogliamo inserire nella tabella, quindi quelli contenuti nell’oggetto “lista”.<br />

Ci resta solamente da inserire un metodo, quello che si occupa di inserire gli elementi nelle celle<br />

della tabella. Ecco il metodo in questione:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

12<br />

13<br />

14<br />

15<br />

// Setta il contenuto delle varie celle<br />

- (UITableViewCell *)tableView:(UITableView *)tableView<br />

cellForRowAtIndexPath:(NSIndexPath *)indexPath{<br />

!<br />

! UITableViewCell *cell = [tableView<br />

dequeueReusableCellWithIdentifier:@"cellID"];<br />

!<br />

! if (cell == nil){<br />

! ! cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero<br />

reuseIdentifier:@"cellID"] autorelease];<br />

! ! //setta lo stile con cui vengono selezionate le righe<br />

! ! cell.selectionStyle = UITableViewCellSelectionStyleNone;!<br />

! }<br />

! //inseriamo nella cella l'elemento della lista corrispondente<br />

! cell.textLabel.text = [lista objectAtIndex:indexPath.row];<br />

! return cell;<br />

}<br />

Questo è il metodo (fondamentale ed obbligatorio) che si occupa di settare in maniera corretta<br />

le celle della tabella. Alla riga 4 troviamo la dichiarazione di una cella, che viene poi allocata alla<br />

riga 7. Con l’istruzione presente alla riga 9 definiamo come deve essere l’aspetto delle righe<br />

quando vengono selezionate dall’utente. Con questa istruzione l’utente non potrà selezionare<br />

nessuna riga, se invece la togliamo avremo la classica selezione con sfondo blu.<br />

Alla riga 13, infine, settiamo il valore contenuto nella cella: esso deve essere letto dall’array, nella<br />

posizione uguale a quella della riga (ricordatevi che sia la numerazione dell’array che delle celle<br />

parte da zero).<br />

Cliccate ora su “Build and Go!”: la nostra tabella inizia a prendere forma!<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 61


PARTE 2: INSERIAMO ALCUNE FUNZIONALITÀ<br />

Abbiamo visto come definire una tabella. In questa seconda parte vedremo come aggiungere<br />

due funzionalità davvero molto importanti: la cancellazione delle singole celle e la possibilità di<br />

renderle selezionabili. Vedrete che <strong>per</strong> entrambe le caratteristiche dovremo inserire davvero<br />

poco codice, in quanto è già tutto definito.<br />

PERMETTIAMO LA CANCELLAZIONE DI UNA RIGA<br />

La prima cosa da fare è inserire il bottone che <strong>per</strong>mette di accedere alla modifica della tabella.<br />

Per fare ciò ci basta decommentare una riga che dovreste già trovare nel metodo viewDidLoad:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

15<br />

16<br />

17<br />

#import "RootViewController.h"<br />

@implementation RootViewController<br />

@synthesize lista;<br />

- (void)viewDidLoad{<br />

[su<strong>per</strong> viewDidLoad];<br />

! // codice aggiunto nella prima parte del tutorial<br />

...<br />

// Uncomment the following line to display an Edit button in the<br />

navigation bar for this view controller.<br />

self.navigationItem.rightBarButtonItem = self.editButtonItem;<br />

}<br />

Tutto molto semplice e veloce grazie alle API di Apple.<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 62


Se provate ad eseguire l'applicazione noterete che cancellando una riga essa non viene rimossa<br />

dalla tabella. Questo avviene <strong>per</strong>ché non abbiamo ancora concluso di implementare questa<br />

funzionalità. Inseriamo, quindi, il seguente metodo:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

12<br />

// Elimina l'elemento dalla tabella e dalla lista<br />

- (void)tableView:(UITableView *)tableView<br />

commitEditingStyle:(UITableViewCellEditingStyle)editingStyle<br />

forRowAtIndexPath:(NSIndexPath *)indexPath {<br />

!<br />

! //controlla se l'azione compiuta è un'eliminazione<br />

! if (editingStyle == UITableViewCellEditingStyleDelete) {<br />

! ! //elimina l'elemento dalla lista<br />

! ! [lista removeObjectAtIndex:indexPath.row];<br />

! ! //elimina le'elemento dalla tabella<br />

! ! [self.tableView deleteRowsAtIndexPaths:[NSArray<br />

arrayWithObject:indexPath]<br />

withRowAnimation:UITableViewRowAnimationFade];<br />

! !<br />

! }<br />

}<br />

Come possiamo notare dalla struttura un po’ complicata, questo è un metodo del protocollo<br />

UITableView, proprio come quello che abbiamo implementato nella prima parte.<br />

Il costrutto if (riga 5) esegue un controllo che, come spiega il commento, controlla se l’azione<br />

eseguita sulla tabella è di cancellazione di una riga. Direte voi: “Cosa posso fare d’altro?” Per<br />

ora niente, <strong>per</strong>ché la nostra tabella supporta solo l’eliminazione di una riga, ma volendo si potrebbe<br />

implementare anche l’inserimento di una nuova riga, oppure altre azioni. È sempre questo<br />

metodo che si occupa di gestire tutte le azioni sulla tabella. Ecco spiegata la necessità di<br />

questo controllo. Tornando al codice, all’interno dell’if possiamo notare due istruzioni, che<br />

eliminano l’elemento sia dalla lista (riga 7) che dalla tabella (riga 9). In questo modo la cancellazione<br />

di una riga è davvero implementata.<br />

RENDIAMO LE CELLE SELEZIONABILI<br />

Vediamo ora di implementare un’altra funzione. Vogliamo che quando l’utente seleziona una<br />

cella appaia un pop-up che contenga il nome dell’elemento selezionato. Ovviamente questa<br />

azione non ha una grande utilità, ma vi <strong>per</strong>metterà di imparare come gestire le selezioni dell’utente<br />

e vedrete, inoltre, come creare un pop-up.<br />

Prima di implementare il metodo necessario, eliminate dal metodo<br />

tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath;<br />

la seguente istruzione (vi ho spiegato nella prima parte a cosa serviva):<br />

1 cell.selectionStyle = UITableViewCellSelectionStyleNone;<br />

altrimenti le celle non saranno selezionabili.<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 63


Nel solito file “RootViewController.m” inserite ora questo metodo:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

// Se selezioniamo una riga appare un pop-up con l'elemento in questione<br />

- (void)tableView:(UITableView *)tableView<br />

didSelectRowAtIndexPath:(NSIndexPath *)indexPath {<br />

! UIAlertView *popUp = [[UIAlertView alloc] initWithTitle:@"Hai selezionato:"<br />

message:[lista objectAtIndex:indexPath.row]<br />

delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];<br />

! [popUp show];<br />

! [popUp release];<br />

}<br />

Questo è il metodo che si occupa di eseguire una certa azione quando l’utente seleziona una<br />

cella. Alla riga 3 possiamo notare la definizione del pop-up, che conterrà un messaggio con il<br />

nome della cella selezionata. È possibile creare pop-up con diversi bottoni o più messaggi, vi<br />

basterà guardare la documentazione <strong>per</strong> trovare tutte le varianti possibili.<br />

Alla riga 4, infine, viene mostrato il pop-up appena definito.<br />

Cliccate ora su “Build and Go!” e testate la nuova tabella!<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 64


PARTE 3: IMPLEMENTIAMO LA RICERCA<br />

Nella terza e ultima parte di questo lungo tutorial dedicato alle tabelle, vedremo come aggiungere<br />

un box di ricerca. Il comportamento sarà del tutto simile a quello della ricerca presente<br />

nell’applicazione nativa “Contatti”.<br />

Vedrete che questa o<strong>per</strong>azione si rivelerà molto semplice, infatti Apple ha davvero migliorato<br />

questo aspetto con le ultime versioni del <strong>SDK</strong>.<br />

AGGIUNGIAMO IL BOX DI RICERCA<br />

Facciamo doppio clic sul file “RootViewController.xib” <strong>per</strong> aprire IB, in cui dovremo inserire la<br />

nostra barra di ricerca. Dalla Libreria selezioniamo un componente “Search Bar and Search Display<br />

Controller”, e trasciniamolo sopra l’elemento “Table View” che vedete nel Pannello dei<br />

documenti.<br />

Se avete eseguito tutto correttamente la vostra tabella mostrerà ora anche una barra di ricerca:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 65


Ancora una volta davvero tutto molto semplice! Salvate tutto e chiudere pure Interface Buider.<br />

MODIFICHIAMO I METODI GIÀ ESISTENTI<br />

Prima di implementare la ricerca vera e propria, dobbiamo fare delle piccole modifiche ai metodi<br />

già presenti nel nostro progetto.<br />

Iniziamo aprendo il file “RootViewController.h” e completiamo così la definizione della classe:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

@interface RootViewController : UITableViewController {<br />

! NSMutableArray *lista;<br />

! NSMutableArray *filteredListContent;<br />

}<br />

@pro<strong>per</strong>ty (nonatomic, retain) NSMutableArray *lista;<br />

@pro<strong>per</strong>ty (nonatomic, retain) NSMutableArray *filteredListContent;<br />

@end<br />

Abbiamo semplicemente dichiarato una nuova lista (riga 3), che conterrà gli elementi “filtrati”,<br />

ovvero quelli che corrispondono al criterio di ricerca.<br />

Ora dobbiamo modificare i metodi che si occupano dell’inizializzazione della tabella. Iniziamo<br />

dal metodo “viewDidLoad” e dalla funzione “@synthetize”:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 66


1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

12<br />

13<br />

14<br />

15<br />

16<br />

17<br />

18<br />

19<br />

20<br />

21<br />

22<br />

#import "RootViewController.h"<br />

@implementation RootViewController<br />

@synthesize lista, filteredListContent;<br />

- (void)viewDidLoad {<br />

[su<strong>per</strong> viewDidLoad];<br />

!<br />

! self.title = @"Prodotti Apple";<br />

!<br />

! //elementi da visualizzare nella tabella<br />

! lista = [[NSMutableArray alloc] initWithObjects:@"<strong>iPhone</strong>", @"i-<br />

Pod", @"iPod Touch", @"iMac", @"iBook", @"MacBook", @"MacBook Pro",<br />

@"Mac Pro", @"PowerBook", nil];<br />

! ! !<br />

// Uncomment the following line to display an Edit button in the<br />

navigation bar for this view controller.<br />

self.navigationItem.rightBarButtonItem = self.editButtonItem;<br />

!<br />

! // crea la lista filtrata, inizializzandola con il numero di<br />

elementi dell'array "lista"<br />

! filteredListContent = [[NSMutableArray alloc] initWithCapacity:<br />

[lista count]];<br />

! //inserisce in questa nuova lista gli elementi della lista originale<br />

! [filteredListContent addObjectsFromArray: lista];<br />

}<br />

Potete notare che la prima parte del metodo “viewDidLoad” è uguale a quella che già abbiamo<br />

scritto nei precedenti tutorial. Alle righe 19 e 21, invece, abbiamo inserito due istruzioni, che<br />

hanno il compito di inizializzare il nuovo array, che ci servirà nell’algoritmo di ricerca. Inizialmente<br />

questa lista coinciderà con quella degli elementi iniziali, mentre poi verrà modificata<br />

mentre l’utente inserisce la stringa di ricerca.<br />

Il secondo metodo da modificare è “numberOfRowsInSection”. Ecco il nuovo codice:<br />

1<br />

2<br />

3<br />

4<br />

- (NSInteger)tableView:(UITableView *)tableView<br />

numberOfRowsInSection:(NSInteger)section{<br />

! //il numero di righe deve corrispondere al numero di elementi<br />

della lista<br />

! return [filteredListContent count];<br />

}<br />

Questa modifica va eseguita in quanto la tabella ora non è più composta dagli elementi della<br />

lista originale, ma da quelli della lista filtrata, ovvero di quegli elementi selezionati mediante la<br />

ricerca. Ovviamente se l’utente non esegue nessuna ricerca, gli elementi della lista filtrata corrisponderanno<br />

agli elementi della lista originale.<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 67


Se vi è chiaro questo ragionamento, è facile intuire quali saranno i prossimi metodi da modificare:<br />

il primo è “cellForRowAtIndexPath:”, ovvero il metodo che si occupa di inserire i valori<br />

nelle celle. Modificate l’ultima istruzione al suo interno nella seguente maniera:<br />

1<br />

2<br />

/inseriamo nella cella l'elemento della lista corrispondente<br />

! cell.textLabel.text = [filteredListContent<br />

objectAtIndex:indexPath.row];<br />

Modifichiamo, poi, il metodo “commitEditingStyle”, aggiungendo l’istruzione alla riga 8:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

12<br />

13<br />

- (void)tableView:(UITableView *)tableView<br />

commitEditingStyle:(UITableViewCellEditingStyle)editingStyle<br />

forRowAtIndexPath:(NSIndexPath *)indexPath {<br />

!<br />

! //controlla se l'azione compiuta è un'eliminazione<br />

! if (editingStyle == UITableViewCellEditingStyleDelete) {<br />

! ! NSLog(@"cancellato");<br />

! ! //elimina l'elemento dalle due liste<br />

! ! [lista removeObjectAtIndex:indexPath.row];<br />

! ! [filteredListContent removeObjectAtIndex:indexPath.row];<br />

! ! //elimina le'elemento dalla tabella<br />

! ! [self.tableView deleteRowsAtIndexPaths:[NSArray<br />

arrayWithObject:indexPath]<br />

withRowAnimation:UITableViewRowAnimationFade];<br />

! !<br />

! }<br />

}<br />

L’ultimo metodo da modificare, infine, è “didSelectRowAtIndexPath:” e anche in questo caso<br />

l’unica modifica riguarda proprio la lista di riferimento.<br />

1<br />

2<br />

3<br />

4<br />

5<br />

- (void)tableView:(UITableView *)tableView<br />

didSelectRowAtIndexPath:(NSIndexPath *)indexPath {<br />

! UIAlertView *popUp = [[UIAlertView alloc] initWithTitle:@"Hai<br />

selezionato:" message:[filteredListContent<br />

objectAtIndex:indexPath.row] delegate:self cancelButtonTitle:@"OK"<br />

otherButtonTitles:nil];<br />

! [popUp show];<br />

! [popUp release];<br />

}<br />

Abbiamo così eseguito tutte le modifiche necessarie!<br />

IMPLEMENTIAMO LA RICERCA<br />

È arrivato il momento di implementare la ricerca vera e propria. Prima di mostrarvi i passaggi<br />

necessari, devo premettere che il codice non è stato scritto da me, ma l’ho preso da un esempio<br />

realizzato dalla stessa Apple. I commenti, quindi, saranno davvero pochi, anche <strong>per</strong>ché non è<br />

fondamentale capire come funziona tale algoritmo, in quanto lo stesso codice si può utilizzare<br />

in qualsiasi altra applicazione che necessiti di una ricerca.<br />

Iniziate inserendo questi due metodi:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 68


1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

12<br />

13<br />

14<br />

15<br />

16<br />

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller<br />

shouldReloadTableForSearchString:(NSString *)searchString{<br />

[self filterContentForSearchText:searchString scope:<br />

! [[self.searchDisplayController.searchBar scopeButtonTitles]<br />

objectAtIndex:[self.searchDisplayController.searchBar selectedScope-<br />

ButtonIndex]]];<br />

// Return YES to cause the search result table view to be reloaded.<br />

return YES;<br />

}<br />

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller<br />

shouldReloadTableForSearchScope:(NSInteger)searchOption{<br />

!<br />

[self<br />

filterContentForSearchText:[self.searchDisplayController.searchBar<br />

text] scope:<br />

! [[self.searchDisplayController.searchBar scopeButtonTitles]<br />

objectAtIndex:searchOption]];<br />

// Return YES to cause the search result table view to be reloaded.<br />

return YES;<br />

}<br />

I due metodi appena mostrati fanno parte del delegato “UISearchDisplayController”, che si<br />

occupa di gestire in maniera corretta la barra di ricerca.<br />

Ora dobbiamo inserire l’algoritmo di ricerca vero e proprio. Eccovelo:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

12<br />

13<br />

14<br />

- (void)filterContentForSearchText:(NSString*)searchText<br />

scope:(NSString*)scope{<br />

!<br />

! // <strong>per</strong> prima cosa azzeriamo l'array della ricerca<br />

! [self.filteredListContent removeAllObjects];<br />

!<br />

! // controlliamo se gli elementi della tabella corrispondono alla<br />

ricerca<br />

! NSString *cellTitle;<br />

! for (cellTitle in lista){<br />

! ! NSComparisonResult result = [cellTitle compare:searchText<br />

options:NSCaseInsensitiveSearch range:NSMakeRange(0, [searchText<br />

length])];<br />

! ! if (result == NSOrderedSame){<br />

! ! ! [filteredListContent addObject:cellTitle];<br />

! ! }<br />

! }<br />

}<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 69


Per questo algoritmo non voglio spendere parole, in quanto, come detto in precedenza, è stato<br />

scritto da Apple, quindi non posso <strong>per</strong>mettermi di fare modifiche!<br />

Cliccate ora su “Build and Go!”, se avete eseguito tutto correttamente si aprirà la vostra applicazione<br />

con la barra di ricerca <strong>per</strong>fettamente funzionante!<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 70


Capitolo 10: gestiamo più viste (file “.xib” multipli)<br />

In questo capitolo vedremo un’aspetto fondamentale nella creazione di un’applicazione, ovvero<br />

la gestione di più viste. In tutte le applicazioni, infatti, sono presenti diverse viste (“finestre”,<br />

<strong>per</strong> usare un termine più generico), che vengono spesso create con Interface Builder (e quindi<br />

diversi file “.xib”) data la sua comodità.<br />

L’applicazione che andremo a realizzare sarà davvero molto semplice, infatti consisterà in due<br />

semplici viste, che potremo scambiare semplicemente cliccando su un bottone. È importante<br />

seguire bene tutti i passaggi, in modo che possiate replicare la stessa struttura anche nelle vostre<br />

applicazioni più complesse, senza errori e senza <strong>per</strong>dere tempo prezioso.<br />

CREIAMO UN NUOVO PROGETTO<br />

Iniziamo il nostro tutorial creando un nuovo progetto di tipo “View-based application” e chiamiamolo<br />

“view<strong>Tutorial</strong>”<br />

Il template di XCode ci mette già a disposizione una vista, che sarà quella di partenza (quella<br />

che viene caricata all’avvio dell’applicazione, chiamata in questo caso “view<strong>Tutorial</strong>ViewController”).<br />

Creiamo, <strong>per</strong> prima cosa, la seconda vista necessaria <strong>per</strong> questa mini-applicazione.<br />

Facciamo clic con il tasto destro sul nome del nostro progetto e selezioniamo “Add -> New File…”.<br />

Scegliamo, poi, un template “UIViewController” e spuntiamo la voce “With XIB for user<br />

interface”:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 71


Inseriamo come nome “VistaDue” e clicchiamo su “Finish”. Abbiamo così creato una nuova vista<br />

con la relativa classe che la gestisce, niente di più semplice!<br />

DEFINIAMO LA PRIMA VISTA<br />

Apriamo il file “view<strong>Tutorial</strong>ViewController.h” e inseriamo le seguenti dichiarazioni:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

12<br />

13<br />

#import <br />

@class VistaDue;<br />

@interface view<strong>Tutorial</strong>ViewController : UIViewController {<br />

! IBOutlet VistaDue *vistaDueController;<br />

}<br />

@pro<strong>per</strong>ty (nonatomic, retain) IBOutlet VistaDue *vistaDueController;<br />

-(IBAction)cambiaVista;<br />

@end<br />

Alla riga 6 abbiamo definito un elemento di tipo VistaDue, che sarà proprio la vista che caricheremo.<br />

Abbiamo, inoltre, definito anche un’azione “cambiaVista”, che assoceremo ad un pulsante,<br />

sarà l’evento che avvierà il cambio di vista.<br />

Salviamo il file appena modificato e apriamo il file ”view<strong>Tutorial</strong>ViewController.xib”. In Interface<br />

Builder apriamo il Pannello dei documenti e inseriamo un elemento del tipo “UIView-<br />

Controller” al suo interno:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 72


Selezioniamo il componente appena inserito e dal pannello Identity Inspector selezioniamo<br />

come classe “VistaDue”:<br />

Ora inserite nella vista principale (non nel ViewController che abbiamo appena inserito) un<br />

bottone. Ecco come si presenta la mia vista:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 73


Ora selezionate il File’s Owner. Dobbiamo collegare i due componenti che abbiamo definito<br />

poco fa. Colleghiamo l’azione “cambiaVista” con il bottone, selezionando “Touch Up Inside”<br />

quando appare il menù di scelta dell’azione. Collegate, infine, l’elemento “vistaDueController”<br />

con l’UIViewController che abbiamo inserito poco prima. Se avete eseguito tutto correttamente<br />

avrete un pannello che si presenta così:<br />

Possiamo salvare e chiudere questa vista.<br />

DEFINIAMO LA “VISTADUE”<br />

Dobbiamo ora definire la seconda vista. Apriamo <strong>per</strong> prima cosa il file “VistaDue.h” e definite<br />

semplicemente questa azione (riga 7):<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

#import <br />

@interface VistaDue : UIViewController {<br />

}<br />

-(IBAction)tornaIndietro;<br />

@end<br />

Salvate il file e apriamo “VistaDue.xib”. Anche in questo caso inseriamo solamente un bottone<br />

nella vista, che ci <strong>per</strong>metterà di tornare alla prima vista:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 74


Selezioniamo il File’s Owner e colleghiamo l’azione “tornaIndietro” con il bottone che abbiamo<br />

inserito, selezionando sempre “Touch Up Inside” come azione:<br />

Salviamo e chiudiamo pure Interface Builder.<br />

SCRIVIAMO IL CODICE NECESSARIO<br />

Dobbiamo ora scrivere il codice che ci <strong>per</strong>metterà di passare da una vista all’altra. Vedrete che<br />

le istruzioni necessarie saranno davvero poche.<br />

Apriamo il file “view<strong>Tutorial</strong>ViewController.m” e inseriamo il seguente codice:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 75


1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

12<br />

#import "view<strong>Tutorial</strong>ViewController.h"<br />

#import "VistaDue.h"<br />

@implementation view<strong>Tutorial</strong>ViewController<br />

@synthesize vistaDueController;<br />

-(IBAction)cambiaVista{<br />

! vistaDueController = [[VistaDue alloc]<br />

initWithNibName:@"VistaDue" bundle:nil];<br />

! vistaDueController.modalTransitionStyle = UIModalTransition-<br />

StyleFlipHorizontal;<br />

! [self presentModalViewController:self.vistaDueController<br />

animated:YES];<br />

}<br />

Alla riga 9 abbiamo inizializzato la vista, inserendo anche il nome del file .xib che deve essere<br />

caricato. La riga 10, invece, ci <strong>per</strong>mette di impostare l’animazione del passaggio dalla prima alla<br />

seconda vista. Ci sono tre animazioni già predisposte e disponibili:<br />

1. UIModalTransitionStyleCoverVertical, il caricamento della nuova vista sarà verticale, dal basso<br />

verso l’alto;<br />

2. UIModalTransitionStyleFlipHorizontal, c’è la rotazione flip-side, ovvero come se venisse mostrato<br />

il retro della vista;<br />

3. UIModalTransitionStyleCrossDissolve, dissolvenza incrociata.<br />

L’ultima istruzione (riga 11) <strong>per</strong>mette di mostrare la seconda vista, rendendola così visibile all’utente.<br />

Ora non ci resta che definire il metodo “tornaIndietro” della classe VistaDue. Apriamo il file<br />

“VistaDue.m” e inseriamo la definizione di tale metodo:<br />

1<br />

2<br />

3<br />

- (IBAction)tornaIndietro{<br />

! [[self parentViewController]<br />

dismissModalViewControllerAnimated:YES];<br />

}<br />

Questa istruzione ci <strong>per</strong>mette di uscire dalla vista corrente e tornare a quella che era visualizzata<br />

precedentemente (nel nostro caso la vista “view<strong>Tutorial</strong>ViewController”).<br />

Abbiamo concluso! Clicchiamo su “Build and Run” e controlliamo che l’applicazione funzioni<br />

correttamente!<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 76


<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 77


Capitolo 11: Come creare una TabBar Application<br />

Uno dei componenti più utilizzati (e uno dei più apprezzati dagli utenti finali) sono le TabBar,<br />

che avete già conosciuto nel capitolo 2. In questo tutorial vedremo come creare una struttura<br />

di base, inserendo due viste generiche e una più particolare e utile: una tabella integrata ad una<br />

NavigationBar, che ci <strong>per</strong>metterà di navigare nei sottolivelli della tabella (<strong>per</strong> capirci, la struttura<br />

che è presente nell’applicazione nativa iPod).<br />

PARTE 1: LA STRUTTURA DI BASE<br />

Abbiamo già descritto cosa faremo in questa prima parte: realizzeremo la struttura di base, che<br />

ci <strong>per</strong>metterà di inserire diverse viste nella tab. È importante seguire bene tutti i passaggi <strong>per</strong><br />

non ritrovarsi con errori strani, che spesso portano a <strong>per</strong>dere tempo e possono essere facilmente<br />

evitati.<br />

CREIAMO UNA TABBAR “PULITA”<br />

Iniziamo creando un nuovo progetto di tipo “Tab Bar Application” e chiamandolo “TabBar<strong>Tutorial</strong>”.<br />

Vogliamo andare a definire una struttura di base pulita, <strong>per</strong>sonalizzandola poi a nostro<br />

piacimento. Eliminiamo, quindi, alcuni componenti che XCode ha già creato <strong>per</strong> noi, ma che<br />

non vogliamo sfruttare: cancelliamo il file “SecondView.xib”, “FirstViewController.h” e<br />

“FirstViewController.m”.<br />

Possiamo ora fare doppio clic su “MainWindow.xib”, si aprirà Interface Builder che ci mostrerà<br />

questo layout <strong>per</strong> la nostra applicazione:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 78


Selezioniamo ognuno dei tab ed eliminiamolo, ottenendo questa struttura:<br />

Salviamo questo file e chiudiamo pure Interface Builder.<br />

DEFINIAMO LE DUE VISTE<br />

Dobbiamo ora definire le due viste che dovremo inserire nella nostra applicazione. Dal menù<br />

“File” scegliamo “New File…” e selezioniamo “Empty XIB”. Creiamo due di questi file chiamandoli,<br />

rispettivamente, “PrimaVista” e “SecondaVista”.<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 79


Nella cartella “Resources” del nostro progetto vedremo i due file appena creati:<br />

Dobbiamo ora creare anche le due classi che gestiranno le due viste: nel tutorial non serviranno<br />

a niente, ma voglio implementarle in modo da darvi già una struttura che potrete utilizzare nelle<br />

vostre applicazioni.<br />

Andiamo, quindi, in “File -> New File…” e spostiamoci nella sezione “Cocoa Touch Class”, in<br />

cui selezioniamo il modello “UIViewController”: anche in questo caso dobbiamo creare due<br />

classi, chiamate “PrimaVistaController” e “SecondaVistaController”.<br />

Possiamo spostare i file appena creati nella sezione “Classes” del nostro progetto. Abbiamo così<br />

definito tutti i componenti necessari, non ci resta che definire la struttura grafica delle due viste.<br />

CREIAMO L’ASPETTO GRAFICO DELLE DUE VISTE<br />

Clicchiamo su “PrimaVista.xib” <strong>per</strong> aprirla in Interface Builder. Dalla Libreria, inseriamo una<br />

“UIView” all’interno del Pannello dei Documenti (”Tools -> Reveal in Document Window”).<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 80


Apriamo la vista appena inserita e modifichiamone l’aspetto a nostro piacimento (io <strong>per</strong> semplicità<br />

inserirò solo due label, in questo tutorial non ci servirà altro). Dall’”Attributes Inspector”<br />

selezioniamo “Tab Bar” dal sotto-menù a tendina “Bottom Bar”:<br />

Questa proprietà non ha nessun fine pratico, <strong>per</strong>ò ci consente di aver una visione completa della<br />

nostra vista, tenendo in considerazione anche la tab bar (in questo modo saprete esattamente<br />

quanto spazio avete a disposizione <strong>per</strong> i vostri componenti). Ecco come si presenta la nostra<br />

vista:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 81


Ora dobbiamo collegare questa vista con la classe che abbiamo definito in precedenza. Sempre<br />

dal Pannello dei Documenti selezioniamo il “File’s Owner”:<br />

In “Identity Inspector” selezioniamo “PrimaVistaController” dal menù a tendina “Class”.<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 82


Andiamo poi in “Connections Inspector” e colleghiamo l’elemento “view” con la vista che abbiamo<br />

appena creato. Se abbiamo eseguito il passaggio in maniera corretta avremo questo risultato:<br />

Abbiamo così completato la definizione della vista. Eseguiamo lo stesso procedimento anche<br />

<strong>per</strong> il file “SecondaVista.xib”, collegandola <strong>per</strong>ò alla classe “SecondaVistaController”. Possiamo<br />

poi salvare tutto e chiudere Interface Builder.<br />

IMPOSTIAMO LA TABBAR<br />

Ora è giunto il momento di impostare la struttura vera e propria della nostra Tab Bar. Apriamo<br />

il file “MainWindow.xib”<br />

Dalla Libreria inseriamo due componenti UIViewController trascinandoli nella “Tab Bar” posta<br />

a fondo vista:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 83


Il risultato finale sarà il seguente:<br />

Iniziamo facendo clic sul primo elemento, facendo attenzione che si evidenzi in questo modo:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 84


Per prima cosa impostiamo la classe di questo UIViewController. Andiamo nel pannello “Identity<br />

Inspector” e selezioniamo “PrimaVistaController” come classe:<br />

È molto importante non saltare questo primo passo, altrimenti <strong>per</strong> viste di una certa complessità<br />

riceverete errori strani che non sapete da cosa dipendono, il tutto solamente <strong>per</strong> non aver<br />

impostato la classe della vista!<br />

Poi nel pannello “Attributes Inspector” selezioniamo “PrimaVista” dal menù “NIB Name”:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 85


Ora facciamo doppio clic sul nome del tab (che <strong>per</strong> default è “Item”), e rinominiamolo a nostro<br />

piacere. Ripetiamo, poi, lo stesso procedimento con il secondo tab, associando questa volta la<br />

“SecondaVista”.<br />

Se avete eseguito tutto in maniera corretta avrete il seguente risultato:<br />

Chiudiamo ora Interface Builder, salvando tutti i file. Da XCode clicchiamo su “Build and Go!”<br />

e testiamo se tutto funziona in maniera corretta!<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 86


PARTE 2: INSERIAMO UNA NAVIGATIONBAR<br />

Nella seconda parte di questo tutorial analizzeremo l’aspetto più importante e più delicato, ovvero<br />

l’implementazione di una UINavigationBar e di una tabella. Questa combinazione ci <strong>per</strong>metterà<br />

di navigare nei sotto-elementi della tabella. Ovvero, quando l’utente seleziona una determinata<br />

cella si aprirà una corrispondente vista che avremo definito con Interface Builder. La<br />

navigation bar, poi, ci <strong>per</strong>metterà di tornare alla tabella principale. Un po’ come avviene nel<br />

menù “Impostazioni” del’<strong>iPhone</strong> / iPod Touch!<br />

CREIAMO UN NUOVO ELEMENTO PER LA TABBAR<br />

Iniziamo creando la classe che gestirà la nuova vista. Dal menù “File” scegliamo “New File…”,<br />

nel pannello che apparirà selezioniamo “UIViewController subclass” e spuntiamo la voce “UI-<br />

TableViewController subclass” presente nelle opzioni. Chiamiamo questa nuova classe “TabellaController”.<br />

Abbiamo già imparato a gestire una tabella nel capitolo 9, quindi non rispiegherò il codice utilizzato.<br />

Riutilizziamo gli stessi metodi, quindi inserite nel file “TabellaController.h” il seguente<br />

codice:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 87


1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

#import <br />

@interface TabellaController : UITableViewController {!<br />

! //array che conterrà gli elementi da visualizzare nella tabella<br />

! NSArray *lista;<br />

}<br />

@pro<strong>per</strong>ty (nonatomic, retain) NSArray *lista;<br />

@end<br />

Mentre in “TabellaController.m” inserite questi metodi:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

12<br />

13<br />

14<br />

15<br />

16<br />

17<br />

18<br />

19<br />

20<br />

21<br />

#import "TabellaController.h"<br />

@implementation TabellaController<br />

@synthesize lista;<br />

- (void)awakeFromNib{!<br />

! // creiamo la lista e inseriamo una serie di elementi da visualizzare<br />

nella nostra tabella<br />

! lista = [[NSArray alloc] initWithObjects:! @"<strong>iPhone</strong>", @"iPod",<br />

@"iPod Touch", @"iMac", @"iBook", @"MacBook", @"MacBook Pro", @"Mac<br />

Pro", @"PowerBook", nil];<br />

}<br />

//setta il numero di sezioni della tabella<br />

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{<br />

! return 1;<br />

}<br />

//setta il numero di righe della tabella<br />

- (NSInteger)tableView:(UITableView *)tableView<br />

numberOfRowsInSection:(NSInteger)section{<br />

! //numero di righe deve corrispondere al numero di elementi della<br />

lista<br />

! return [lista count];<br />

}<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 88


22<br />

23<br />

24<br />

25<br />

26<br />

27<br />

28<br />

29<br />

30<br />

31<br />

32<br />

33<br />

34<br />

35<br />

//settiamo il contenuto delle varie celle<br />

- (UITableViewCell *)tableView:(UITableView *)tableView<br />

cellForRowAtIndexPath:(NSIndexPath *)indexPath{<br />

!<br />

! UITableViewCell *cell = [tableView<br />

dequeueReusableCellWithIdentifier:@"cellID"];<br />

!<br />

! if (cell == nil){<br />

! ! cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero<br />

reuseIdentifier:@"cellID"] autorelease];<br />

! !<br />

! }<br />

! //inseriamo nella cella l'elemento della lista corrispondente<br />

! cell.textLabel.text = [lista objectAtIndex:indexPath.row];<br />

!<br />

! return cell;<br />

}<br />

Salviamo entrambi i file e riapriamo “MainWindow.xib” <strong>per</strong> tornare in Interface Builder.<br />

DEFINIAMO L’ASPETTO DEL NUOVO ELEMENTO<br />

Dalla Libreria prendiamo un componente UINavigationController e inseriamolo nella tab bar,<br />

proprio come abbiamo nella prima parte di questo tutorial.<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 89


Proprio come abbiamo fatto in precedenza cambiamo il nome della scheda in “Tabella”. Ecco il<br />

risultato finale:<br />

Ora non ci resta che inserire la tabella all’interno di questa vista. Dalla Libreria prediamo un<br />

componente UITableViewController e inseriamolo nella nostra vista. Il risultato che dovete<br />

ottenere è il seguente:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 90


Ora dobbiamo solo collegare la classe alla tabella appena inserita. Dal Pannello dei Documenti<br />

(”Tools -> Reveal in Document Window”) navighiamo fino al seguente <strong>per</strong>corso:<br />

Come mostrato in figura, selezioniamo il componente “Table View Controller” (che non è altro<br />

che la nostra tabella) e apriamo l’”Identity Inspector”. Dal menù Class scegliamo “TabellaController”:<br />

Abbiamo così concluso con la creazione della nostra tabella. Salviamo tutto, torniamo in XCode<br />

e clicchiamo su “Build and Go!”: la tabella sarà ora presente e funzionante nell’applicazione!<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 91


IMPLEMENTIAMO DUE VISTE DI DETTAGLIO<br />

Ora vediamo di analizzare un aspetto che molti utenti mi hanno chiesto via mail. Se noi volessimo<br />

associare un determinato file “xib” (ovvero creato con Interface Builder) ad una cella, come<br />

potremmo fare? In questa seconda parte del tutorial vedremo proprio di analizzare i passaggi<br />

necessari. Andremo a definire due viste, una che conterrà una foto dell’elemento “<strong>iPhone</strong>”,<br />

mentre un’altra che avviserà l’utente dell’assenza di informazioni <strong>per</strong> un determinato prodotto.<br />

Ovviamente potreste realizzare una vista con i dettagli <strong>per</strong> ogni prodotto presente nella<br />

tabella, ma il meccanismo rimane invariato.<br />

Iniziamo creando due nuovi file xib, dal menù “File -> New File…” e scegliendo “Empty XIB”.<br />

Io ho chiamato il primo file “<strong>iPhone</strong>Detail” e il secondo “OtherDetail”, ma nulla vieta di chiamarli<br />

in modo diverso!<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 92


Procediamo proprio come abbiamo fatto all’inizio dello scorso tutorial <strong>per</strong> le viste “PrimaVista”<br />

e “Seconda Vista”, quindi definiamo subito via codice le due classi necessarie.<br />

Andiamo, quindi, in “File -> New File…” e spostiamoci nella sezione “Cocoa Touch Class”, in<br />

cui selezioniamo il modello “UIViewController”: anche in questo caso dobbiamo creare due<br />

classi, chiamate “<strong>iPhone</strong>DetailController” e “OtherDetailController”.<br />

Possiamo spostare i file appena creati nella sezione “Classes” del nostro progetto. Ora siamo<br />

pronti <strong>per</strong> definire l’aspetto di queste due nuove viste.<br />

DEFINIAMO L’ASPETTO DELLE DUE VISTE DI DETTAGLIO<br />

Apriamo il file “<strong>iPhone</strong>Detail.xib” in Interface Builder. Il procedimento è, come già detto,<br />

uguale a quello svolto <strong>per</strong> la definizione delle due viste “PrimaVista” e “SecondaVista”. Inseriamo,<br />

quindi, un componente UIView nel Pannello dei Documenti e modifichiamolo a nostro<br />

piacimento. Io ho inserito una foto di un <strong>iPhone</strong>, ovviamente voi potrete inserire quello che<br />

volete. Ecco come risulta essere la mia vista:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 93


Ora associamo questa vista alla sua classe. Dal Pannello dei Documenti selezioniamo il “File’s<br />

Owner” e nell’”Identity Inspector” selezioniamo “<strong>iPhone</strong>DetailController” come classe:<br />

Andiamo poi in “Connections Inspector” e colleghiamo l’elemento “view” con la vista che abbiamo<br />

appena creato (quella contenente le due label <strong>per</strong> intenderci). Se abbiamo eseguito il<br />

passaggio in maniera corretta avremo questo risultato:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 94


Abbiamo così completato la definizione della vista. Eseguiamo lo stesso procedimento anche<br />

<strong>per</strong> il file “OtherDetail.xib”, collegandola <strong>per</strong>ò alla classe “OtherDetailController”. Ecco come<br />

appare tale vista:<br />

Possiamo salvare tutto e chiudere Interface Builder.<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 95


COME RICHIAMARE LE DUE VISTE VIA CODICE<br />

Ora non ci resta che analizzare il codice che ci <strong>per</strong>mette di aprire queste due viste. Apriamo il<br />

file “TabellaController.h” e modifichiamolo nella seguente maniera:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

12<br />

13<br />

14<br />

15<br />

#import <br />

#import "<strong>iPhone</strong>DetailController.h"<br />

#import "OtherDetailController.h"<br />

@interface TabellaController : UITableViewController {!<br />

! //array che conterrà gli elementi da visualizzare nella tabella<br />

! NSArray *lista;<br />

! //controller della vista che dovrà essere a<strong>per</strong>ta<br />

! UIViewController *detail;<br />

}<br />

@pro<strong>per</strong>ty (nonatomic, retain) NSArray *lista;<br />

@end<br />

Abbiamo <strong>per</strong> prima cosa importato le due classi delle viste (righe 2 e 3), e poi definito una vista<br />

generica (riga 10), che poi inizializzeremo con la classe “<strong>iPhone</strong>DetailController” oppure “OtherDetailController”,<br />

a seconda del caso. Perché abbiamo utilizzato “UIViewController” come<br />

tipo dell’elemento “detail”? Perchè abbiamo sfruttato un paradigma della programmazione ad<br />

oggetti, che ci <strong>per</strong>mette di definire un elemento con una su<strong>per</strong>classe, <strong>per</strong> poi inizializzarlo con<br />

una sottoclasse più specifica.<br />

Ora apriamo il file “TabellaController.m” e inseriamo il metodo che viene richiamato quando si<br />

clicca su una cella:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 96


1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

12<br />

13<br />

14<br />

15<br />

16<br />

17<br />

// Metodo relativo alla selezione di una cella<br />

- (void)tableView:(UITableView *)tableView<br />

didSelectRowAtIndexPath:(NSIndexPath *)indexPath {<br />

!<br />

! if (indexPath.row == 0){<br />

! ! //l'utente ha cliccato sull'elemento <strong>iPhone</strong>, quindi carichiamo<br />

la vista relativa<br />

! ! detail = [[<strong>iPhone</strong>DetailController alloc]<br />

initWithNibName:@"<strong>iPhone</strong>Detail" bundle:[NSBundle mainBundle]];<br />

! } else {<br />

! ! detail = [[OtherDetailController alloc]<br />

initWithNibName:@"OtherDetail" bundle:[NSBundle mainBundle]];<br />

! }<br />

!<br />

! //Facciamo visualizzare la vista con i dettagli<br />

! [self.navigationController pushViewController:detail<br />

animated:YES];<br />

! //rilasciamo il controller<br />

! [detail release];<br />

!<br />

! detail = nil;<br />

}<br />

Anche questo metodo lo avevamo già trovato nel tutorial dedicato alle tabelle. Analizziamo,<br />

<strong>per</strong>ò, il codice al suo interno. Troviamo inizialmente un controllo if (riga 4), che controlla se<br />

l’utente ha selezionato al prima cella, ovvero quella contenente l’elemento <strong>iPhone</strong>: se il controllo<br />

da esito positivo, inizializziamo l’elemento “detail” con la classe relativa alla vista “<strong>iPhone</strong>-<br />

Detail” (riga 6), altrimenti con l’altra vista generica (riga 8). La clausola “initWithNibName” si<br />

riferisce proprio al file xib che deve essere associato all’elemento “detail”.<br />

Dopo il ciclo troviamo le istruzioni che ci <strong>per</strong>mettono di far apparire la nuova vista; non<br />

preoccupatevi troppo, sono sempre queste istruzioni da utilizzare.<br />

Abbiamo concluso!! Clicchiamo su “Build and Go!” e godiamoci la nostra applicazione funzionante!!<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 97


<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 98


Capitolo 12: XML<br />

Dopo aver visto molti componenti, in questo capitolo vedremo come integrare una tecnologia<br />

molto utilizzata, specialmente in ambito web: stiamo parlando di XML.<br />

Vedremo, quindi, come leggere un file XML, da cui ricaveremo delle informazioni che abbiamo<br />

salvato. Questa o<strong>per</strong>azione verrà eseguita in locale (ovvero il file xml sarà all’interno del nostro<br />

progetto), ma nulla vieta di avere il file caricato su un server web da cui accediamo tramite la<br />

nostra applicazione.<br />

COSA È XML?<br />

XML è un metalinguaggio (in quanto non è un linguaggio di programmazione vero e proprio)<br />

di markup, ovvero un linguaggio che consente di estendere o controllare il comportamento di<br />

altri linguaggi. Il linguaggio di markup più famoso è sicuramente l’HTML, che ha molte analogie<br />

con l’XML.<br />

XML è l’acronimo di eXtensible Markup Language, da cui possiamo capire la caratteristica<br />

fondamentale di questo linguaggio: ci <strong>per</strong>mette di creare tag <strong>per</strong>sonalizzati, in base alle proprie<br />

esigenze.<br />

Sarà più semplice comprendere come funziona questo linguaggio mediante un esempio:<br />

La prima riga definisce la versione di XML in uso e la codifica utilizzata (secondo le norme<br />

ISO). Dalla seconda riga in poi, invece, troviamo dei tag <strong>per</strong>sonalizzati, che vanno a modellare<br />

dei dati a nostro piacimento.<br />

Possiamo vedere come abbiamo definito un tag generale “studenti”, che viene iniziato alla seconda<br />

riga e concluso all’ultima. Nel mezzo troviamo, invece, altri tag, che riportano le informazioni<br />

che vogliamo memorizzare, <strong>per</strong> poi utilizzarle a nostro piacimento.<br />

Ci sono alcune piccole regole da rispettare nella struttura XML:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 99


1. I tag non possono iniziare con numeri o caratteri speciali e non possono contenere spazi.<br />

Corretti: , , <br />

Errati: , , <br />

2. I tag devono essere bilanciati (ogni tag a<strong>per</strong>to deve essere chiuso)<br />

Corretto: Andrea<br />

Errato: Andrea<br />

3. I tag non devono contenere errori di annidamento.<br />

Ecco alcuni esempi errati:<br />

4. Si possono inserire degli attributi all’interno dei tag; la struttura sarà quindi la seguente:<br />

Valore <br />

I nostri elementi, quindi, potranno essere scritti anche nella seguente maniera:<br />

Questa struttura è del tutto uguale a quella precedente. Notate che in questo caso non abbiamo<br />

usato il tag di chiusura, ma abbiamo inserito “/” all’interno del tag stesso proprio <strong>per</strong><br />

indicare che quel tag non ha elemento di chiusura. Quello che cambierà sarà solamente il<br />

modo di leggere i valori via codice.<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 100


XML NEL <strong>SDK</strong> DI IPHONE<br />

Per ora abbiamo fatto una panoramica su XML in generale, presentando gli aspetti fondamentali<br />

di tale linguaggio. Ma come possiamo integrarlo con le nostre applicazioni? L’oggetto che si<br />

occupa di recu<strong>per</strong>are i dati da un file XML viene detto parser.<br />

Esistono vari tipi di parser (diversi <strong>per</strong> linguaggi e tecnologie), noi andremo ad utilizzare SAX.<br />

La caratteristica di questo parser sta nel fatto che processa i documenti linea <strong>per</strong> linea: dati a<br />

cui si è acceduto in precedenza non possono essere riletti senza la rielaborazione dell’intero<br />

documento. Può essere uno svantaggio, ma è l’unico parser disponibile nel <strong>SDK</strong> <strong>per</strong> <strong>iPhone</strong>!!<br />

CREIAMO LA STRUTTURA GRAFICA<br />

Iniziamo ora a creare la nostra applicazione. Creiamo un nuovo progetto di tipo “View-Based<br />

Application” e chiamiamolo “xml<strong>Tutorial</strong>”.<br />

Prima di definire l’aspetto grafico, <strong>per</strong>ò, dichiariamo i componenti che ci servono. Apriamo il<br />

file “xml<strong>Tutorial</strong>ViewController.h” e modificatelo così:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

#import <br />

@interface xml<strong>Tutorial</strong>ViewController : UIViewController <br />

{<br />

! IBOutlet UITextView *textArea;<br />

!<br />

! NSString *path;<br />

}<br />

-(IBAction)avviaParsing;<br />

@end<br />

Abbiamo dichiarato una TextView in cui inseriremo i dati letti dal file xml, un’azione, che andrà<br />

collegata ad un bottone (tale azione farà iniziare il processo di parsing) e una stringa che<br />

conterrà il <strong>per</strong>corso del file xml. Possiamo salvare il file e dedicarci alla struttura grafica dell’applicazione.<br />

Ricordatevi, anche, di inserire nell’intestazione della classe il delegato<br />

“NSXMLParserDelegate” (riga 3).<br />

Apriamo ora il file “xml<strong>Tutorial</strong>ViewControlle.xib”, che avvierà Interface Builder. Nella nostra<br />

applicazione, inseriamo un bottone e una TextView, di dimensioni abbastanza ampie, in quanto<br />

dovrà contenere tutti i valori letti dal file xml. Dovreste ottenere un risultato come questo:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 101


Ora, selezionando la UITextView, entriamo in “Attributes Inspector” e togliamo la spunta a<br />

“Editable”:<br />

questo <strong>per</strong>ché non vogliamo che l’utente possa modificare i valori presenti nella TextView (ovvero<br />

deve essere di sola lettura).<br />

Dal pannello dei documenti (”Tools -> Reveal in Document Window”) selezioniamo “File’s<br />

Owner”, ovvero la classe che gestisce il nostro file.<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 102


Apriamo il “Connections Inspector” e potremo vedere alcuni elementi, più i due che abbiamo<br />

definito noi all’inizio del nostro progetto. Colleghiamo “textArea” con la UITextView presente<br />

nella nostra vista, e l’azione “avviaParsing” con il bottone: quando apparirà il menù con tutte le<br />

azioni disponibili, scegliamo “Touch Up Inside”. Se avrete eseguito tutto correttamente avrete<br />

un pannello che si presenterà così:<br />

Abbiamo terminato la creazione della struttura grafica. Possiamo salvare tutto e chiudere Interface<br />

Builder.<br />

SCRIVIAMO IL CODICE NECESSARIO<br />

Prima di procedere con il codice necessario, dobbiamo inserire all’interno del progetto il file<br />

xml con i nostri dati. Trascinate il file xml (che potete creare ex-novo, oppure creare copiando il<br />

codice presentato nella prima parte di questo tutorial tutorial) all’interno della cartella “Resources”<br />

del nostro progetto, spuntando l’opzione <strong>per</strong> copiarlo nella cartella fisica del progetto:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 103


Apriamo ora il file “xml<strong>Tutorial</strong>ViewController.m” e definiamo il seguente metodo:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

// Metodo eseguito all'avvio della vista<br />

- (void)viewDidLoad {<br />

[su<strong>per</strong> viewDidLoad];<br />

! // definiamo il <strong>per</strong>corso del file xml<br />

! NSString *pathProgetto = [[NSBundle mainBundle] bundlePath];<br />

! path = [[NSString alloc] initWithString:[pathProgetto<br />

stringByAppendingPathComponent:@"dati.xml"]];<br />

}<br />

Questo metodo viene eseguito all’avvio della vista, e ci <strong>per</strong>mette di definire dei comportamenti<br />

che devono essere eseguiti prima di ogni altra cosa. Con le due istruzioni che abbiamo inserito<br />

definiamo il <strong>per</strong>corso del nostro file “dati.xml”: esso viene cercato all’interno della cartella del<br />

nostro progetto. Queste istruzioni sono molto importanti, in quanto non viene definito un<br />

<strong>per</strong>corso assoluto (soluzione sempre sconsigliabile e spesso errata), ma viene definito il <strong>per</strong>corso<br />

effettivo in cui si trova il file.<br />

Dobbiamo ora definire l’azione che viene eseguita quando premiamo sul pulsante. Ecco il codice<br />

da inserire:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 104


1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

12<br />

13<br />

14<br />

15<br />

16<br />

17<br />

18<br />

-(IBAction)avviaParsing{<br />

! //Bisogna convertire il file in una NSURL altrimenti non funziona<br />

! NSURL *xmlURL = [NSURL fileURLWithPath:path];<br />

! // Creiamo il parser<br />

! NSXMLParser *parser = [[ NSXMLParser alloc]<br />

initWithContentsOfURL:xmlURL];<br />

! // Il delegato del parser e' la classe stessa (self)<br />

! [parser setDelegate:self];<br />

! //Effettuiamo il parser<br />

! BOOL success = [parser parse];<br />

! //controlliamo come è andata l'o<strong>per</strong>azione<br />

! if(success == YES){<br />

! ! //parsing corretto<br />

! } else {<br />

! ! //c'è stato qualche errore...<br />

! }<br />

! // Rilasciamo l'oggetto NSXMLParser<br />

! [parser release];<br />

}<br />

Le istruzioni alle righe 3 e 5 ci <strong>per</strong>mettono di definire il parser, partendo dal <strong>per</strong>corso del nostro<br />

file. Alla riga 9 avviamo il processo di parsing, salvando il risultato in una variabile booleana:<br />

se essa vale YES la conversione si è conclusa senza errori (riga 12), altrimenti c’è stato un<br />

errore (che potrebbe essere dovuto ad errori nella struttura del file xml oppure ad errori di<br />

scrittura del codice).<br />

Come potete vedere non si tratta di codice complesso, sono poche istruzioni che dovrebbero<br />

risultarvi chiare.<br />

La parte che viene ora è quella che si occupa di leggere i dati dal file xml. Iniziamo inserendo<br />

questo metodo:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 105


1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

12<br />

13<br />

14<br />

15<br />

16<br />

17<br />

18<br />

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName<br />

namespaceURI:(NSString *)namespaceURI<br />

qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary<br />

*)attributeDict {<br />

!<br />

! if ([elementName isEqualToString:@"studenti"]){<br />

! ! [textArea setText:[[NSString alloc]<br />

initWithFormat:@"%@\nInizio studenti",textArea.text]];<br />

! }<br />

! else if([elementName isEqualToString:@"studente"]){<br />

! ! [textArea setText:[[NSString alloc]<br />

initWithFormat:@"%@\nNuovo studente",textArea.text]];<br />

! }<br />

! else if([elementName isEqualToString:@"matricola"]) {<br />

! ! [textArea setText:[[NSString alloc]<br />

initWithFormat:@"%@\nMatricola: ",textArea.text]];<br />

! }<br />

! else if([elementName isEqualToString:@"cognome"]) {<br />

! ! [textArea setText:[[NSString alloc]<br />

initWithFormat:@"%@\nCognome: ",textArea.text]];<br />

! }!<br />

! else if([elementName isEqualToString:@"nome"]) {<br />

! ! [textArea setText:[[NSString alloc]<br />

initWithFormat:@"%@\nNome: ",textArea.text]];<br />

! }<br />

}<br />

Come potete osservare, vi sono una serie di controlli if, che vanno a testare l’elemento corrente,<br />

<strong>per</strong> riconoscerlo e <strong>per</strong> scrivere una stringa adeguata nella textArea che abbiamo predisposto.<br />

Questo processo è possibile <strong>per</strong>ché conosciamo a priori la struttura del file xml: questo è quasi<br />

sempre vero, in quanto sarebbe quasi impossibile leggere un file xml di cui non conosciamo la<br />

struttura interna.<br />

Il metodo viene, ovviamente, richiamato ogni volta che il parser incontra un nuovo elemento,<br />

cioè l’a<strong>per</strong>tura di un tag.<br />

Per completare il nostro programma mancano solo due metodi:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString<br />

*)string {<br />

! [textArea setText:[[NSString alloc]<br />

initWithFormat:@"%@%@",textArea.text,string]];<br />

}<br />

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName<br />

namespaceURI:(NSString *)namespaceURI<br />

qualifiedName:(NSString *)qName {<br />

! [textArea setText:[[NSString alloc] initWithFormat:@"%@\nFine<br />

elemento: %@",textArea.text,elementName]];<br />

}<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 106


Il primo viene richiamato quando il parser incontra un valore racchiuso tra due tag (l’informazione<br />

vera e propria). Nel nostro caso ci limitiamo a inserirla nella textArea, <strong>per</strong>ò potreste fare<br />

delle o<strong>per</strong>azioni più o meno complesse sulle informazioni che leggete dal file.<br />

L’ultimo metodo, invece, viene richiamato quando il parser incontra un tag di chiusura. Anche<br />

in questo caso l’unica azione che faremo sarà quello di inserire una stringa nella textArea.<br />

Possiamo finalmente cliccare su “Build and Go!” e testare la nostra applicazione funzionante!<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 107


Capitolo 13: SQL<br />

Nel capitolo precedente abbiamo visto come leggere un file XML e fare il parsing dei dati contenuti<br />

al suo interno. Non esiste, <strong>per</strong>ò, solo quella possibilità <strong>per</strong> accedere ad un archivio di dati.<br />

La tecnologia di maggior successo è sicuramente SQL, che si basa su database relazionali. In<br />

questo capitolo vedremo come sfruttare SQLite <strong>per</strong> interfacciarci con un database presente in<br />

locale (quindi salvato all’interno del nostro progetto). Nulla vieta, <strong>per</strong>ò, che il database risieda<br />

su un server remoto, e che quindi la connessione avvenga tramite la rete.<br />

Creeremo, quindi, una tabella in cui andremo ad inserire i valori letti dal nostro database, dopo<br />

aver eseguito una query predefinita.<br />

Devo premettere, <strong>per</strong>ò, che non parlerò di SQL e database relazionali, che devono essere già<br />

conosciuti da chi affronta questo capitolo. È una scelta che potrebbe non piacere a molti di voi,<br />

<strong>per</strong>ò richiederebbe troppo tempo e una trattazione che non può essere fatta in un semplice tutorial.<br />

Detto ciò, è possibile seguire questa guida e concludere con successo l’applicazione, anche<br />

senza conoscere niente di SQL, ovviamente alcune caratteristiche e alcuni passaggi potrebbero<br />

risultare di difficile comprensione.<br />

In questa guida sentirete spesso parlare di SQLite, ma cosa è di preciso?<br />

SQLite è una libreria che implementa un DBMS SQL, <strong>per</strong>mettendo di creare un database all’interno<br />

di un unico file. Esso è molto indicato <strong>per</strong> scopi come il nostro, ovvero la creazione di<br />

applicazioni <strong>per</strong> dispositivi mobili, che non possono <strong>per</strong>mettersi di avere un DMBS dedicato<br />

<strong>per</strong> la gestione delle basi di dati.<br />

Ovviamente fornisce un supporto parziale all’SQL, in quanto manca di alcune caratteristiche<br />

avanzate, che <strong>per</strong>ò dubito possiate utilizzare all’interno di un’applicazione. SQLite, comunque,<br />

è molto veloce e leggero, <strong>per</strong>fetto quindi <strong>per</strong> applicazioni <strong>per</strong> <strong>iPhone</strong>.<br />

DEFINIAMO UN NUOVO PROGETTO<br />

Iniziamo creando un nuovo progetto di tipo “Navigation-based Application” e chiamiamolo<br />

“sql<strong>Tutorial</strong>”. Abbiamo quindi creato un progetto che ci fornisce già l’implementazione di una<br />

tabella, che visualizzerà i dati letti dal nostro database.<br />

Dobbiamo, <strong>per</strong>ò, inserire altre due cose molto importanti: una classe che si occu<strong>per</strong>à di comunicare<br />

con il database, e la libreria che <strong>per</strong>mette tale comunicazione.<br />

Iniziamo creando la classe che serirà ai nostri scopi. Andiamo in “File -> New File…” e creiamo<br />

una “Objective-C class”, chiamandola semplicemente “Data”:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 108


Dobbiamo ora inserire nel nostro progetto la libreria (o framework) che si occupa del collegamento<br />

con il database sql. Clicchiamo con il tasto destro sulla cartella “Frameworks” all’interno<br />

del nostro progetto, poi andiamo in “Add -> Existing Frameworks…” e dall’elenco seguente che<br />

apparirà selezioniamo “libsqlite3.0.dylib”:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 109


Abbiamo così terminato la definizione della struttura principale del nostro progetto. Se avete<br />

eseguito tutto in maniera corretta dovreste avere un progetto come questo:<br />

DEFINIAMO LA CLASSE “DATA”<br />

Dobbiamo ora implementare la classe “Data”, su cui si basa gran parte di questo capitolo. Prima<br />

di iniziare a scrivere codice, focalizziamo l’attenzione su ciò che deve fare questa classe. Essa<br />

avrà il compito di:<br />

• creare una connessione con il database (di cui noi specificheremo un indirizzo, in questo<br />

caso locale, ma nulla vieterebbe di avere un database in remoto);<br />

• interrogare la base di dati eseguendo una query impostata via codice;<br />

• inserire i risultati della query all’interno di un’array, che verrà poi visualizzato all’interno<br />

della tabella.<br />

Vediamo ora di implementare queste funzionalità, più altre caratteristiche che ci serviranno<br />

come supporto.<br />

Iniziamo aprendo il file “Data.h” e inserendo il seguente codice:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 110


1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

12<br />

13<br />

14<br />

15<br />

16<br />

17<br />

#import <br />

#import <br />

@interface Data : NSObject {<br />

! // Lista contenente i dati letti dal database<br />

! NSMutableArray *lista;<br />

}<br />

- (id)init:(NSString *)pathDB;<br />

- (void)caricaValoriDaDB:(NSString *)dbPath;<br />

- (unsigned)getSize;<br />

- (id)objectAtIndex:(unsigned)theIndex;<br />

@pro<strong>per</strong>ty (nonatomic, retain) NSMutableArray *lista;<br />

@end<br />

Alla riga numero 6 abbiamo dichiarato un array (di tipo NSMutableArray, quindi modificabile<br />

anche dopo la sua inizializzazione), che conterrà i valori letti dal database. Dalla riga 10 alla 13<br />

abbiamo definito i metodi che ci serviranno in tale classe, che implementeremo fra poco. Da<br />

notare, inoltre, la classe importata alla riga 2: è necessaria <strong>per</strong> dire alla nostra classe di utilizzare<br />

la libreria che abbiamo importato all’inizio della guida.<br />

Apriamo ora il file “Data.m” e iniziamo ad inserire il seguente codice:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

12<br />

13<br />

14<br />

15<br />

16<br />

17<br />

18<br />

19<br />

20<br />

21<br />

22<br />

23<br />

24<br />

#import "Data.h"<br />

static sqlite3 *database = nil;<br />

@implementation Data<br />

@synthesize lista;<br />

// Inizializziamo l'oggetto della classe Data<br />

- (id)init:(NSString *)pathDB{<br />

! // carichiamo i valori dal database<br />

! [self caricaValoriDaDB:pathDB];<br />

return self;<br />

}<br />

// Ritorna la dimensione della lista (n° di elementi letti dal db)<br />

- (unsigned)getSize {<br />

return [lista count];<br />

}<br />

// Ritorna l'oggetto ad una data posizione<br />

- (id)objectAtIndex:(unsigned)index {<br />

return [lista objectAtIndex:index];<br />

}<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 111


La prima istruzione particolare compare alla riga 3, ed è la definizione dell’oggetto che ci servirà<br />

<strong>per</strong> creare la connessione con il database.<br />

Alla riga 10 viene dichiarato il primo metodo, “init”, che deve essere invocato quando si vuole<br />

inizializzare un oggetto appartenente alla classe Data. Alla riga 12 viene chiamiamo il metodo<br />

“caricaValoriDaDB”, che ha il compito di interfacciarsi con il database ed eseguire le query sui<br />

dati (vedremo fra poco la sua implementazione). Il “return self” alla riga 13, infine, ritorna il<br />

puntatore dell”oggetto appena creato.<br />

Alla riga 17 definiamo “getSize”, un semplice metodo che ci ritorna la dimensione della lista, e<br />

quindi il numero di elementi letti dalla nostra query. Questo ci servirà quando andremo a definire<br />

la tabella.<br />

Infine, alla riga 22, definiamo un metodo che ci ritorna un oggetto presente ad una determinata<br />

posizione della nostra lista. Ad esempio, potremo recu<strong>per</strong>are il 5° elemento della nostra lista,<br />

<strong>per</strong> poi elaborarlo oppure mostrarlo all’utente.<br />

Dobbiamo ora implementare il metodo più complesso di questa classe, ovvero “caricaValori-<br />

DaDB”. Ecco il codice di tale metodo:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 112


1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

12<br />

13<br />

14<br />

15<br />

16<br />

17<br />

18<br />

19<br />

20<br />

21<br />

22<br />

23<br />

24<br />

25<br />

26<br />

27<br />

28<br />

29<br />

30<br />

31<br />

32<br />

33<br />

34<br />

35<br />

36<br />

// Carica i valori dal database passato come parametro<br />

- (void)caricaValoriDaDB:(NSString *)dbPath {<br />

! NSLog(@"path: %@",dbPath);<br />

! // lista temporanea<br />

! NSMutableArray *listaTemp = [[NSMutableArray alloc] init];<br />

! // Oggetto che contiene i vari elementi<br />

NSMutableDictionary *dictionary;<br />

!<br />

! NSMutableString *idPersona;//id della <strong>per</strong>sona<br />

! NSMutableString *nome;//nome della <strong>per</strong>sona<br />

! NSMutableString *cognome;//cognome della <strong>per</strong>sona<br />

!<br />

! if (sqlite3_open([dbPath UTF8String], &database) == SQLITE_OK) {<br />

! ! // query che ricava i valori<br />

! ! const char *sql = "select ID, Nome, Cognome from PERSO-<br />

NA";<br />

! ! sqlite3_stmt *selectstmt;<br />

! !<br />

! ! if(sqlite3_prepare_v2(database, sql, -1, &selectstmt,<br />

NULL) == SQLITE_OK) {<br />

! ! ! while(sqlite3_step(selectstmt) == SQLITE_ROW) {<br />

! ! ! ! // ricaviamo i valori letti dalla query<br />

! ! ! ! idPersona = [NSString<br />

stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 0)];<br />

! ! ! ! nome = [NSString stringWithUTF8String:(char<br />

*)sqlite3_column_text(selectstmt, 1)];<br />

! ! ! ! cognome = [NSString stringWithUTF8String:(char<br />

*)sqlite3_column_text(selectstmt, 2)];<br />

! ! ! ! // inseriamo tutti i valori letti in un unico<br />

oggetto<br />

! ! ! ! dictionary = [[NSMutableDictionary alloc]<br />

initWithObjectsAndKeys:idPersona, @"id", nome, @"nome", cognome,<br />

@"cognome", nil];<br />

! ! ! ! [listaTemp addObject:dictionary];<br />

! ! ! ! [dictionary release];<br />

! ! ! }<br />

! ! }<br />

! ! self.lista = listaTemp;<br />

! ! [listaTemp release];<br />

! }<br />

! else<br />

! ! sqlite3_close(database);<br />

! NSLog(@"tutto ok");<br />

}<br />

Iniziamo ad analizzare questo metodo. Partiamo dall’intestazione, in cui viene definito un parametro<br />

“dbPath”: questo è il <strong>per</strong>corso del nostro database. Esso lo definiremo in seguito, nella<br />

classe che gestisce la tabella. In questo tutorial il database sarà in locale, ovverò sarà fisicamente<br />

presente nella cartella del nostro progetto. Nulla vieta, comunque, di inserire un indirizzo<br />

remoto, che ci consenta di connetterci ad un database presente su un server.<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 113


Subito dopo, creiamo alcuni oggetti, che ci servono <strong>per</strong> gestire i dati ricavati dalle query. Abbiamo,<br />

infatti, un oggetto “dictionary”, che conterrà i vari elementi ricavati dall’interrogazione<br />

al database. Le stringhe “idPersona”, “nome”, “cognome”, infatti, servono <strong>per</strong> salvare i valori<br />

letti, e inserirli all’interno dell’oggetto appena menzionato.<br />

Alla riga 13 viene a<strong>per</strong>ta la connessione con il database: essa si trova all’interno di un costrutto<br />

“if”: se tale controllo da esito positivo, si possono elaborare i dati, altrimenti si passa alla fine<br />

del metodo, in quanto non è possibile instaurare una connessione con il database. Se la connessione<br />

è stata creata, possiamo creare la query che andremo poi ad eseguire (riga 15). Alla riga 18<br />

eseguiamo poi tale query: anche in questo caso, se l’esecuzione ha avuto successo, possiamo<br />

ricavare i valori desiderati, altrimenti non verrà eseguita nessuna o<strong>per</strong>azione.<br />

Il ciclo while (riga 19) ci <strong>per</strong>metterà di scorrere tutti i risultati della nostra query (che potrebbero<br />

essere, ovviamente, più di uno), fino al termine. Potete notare che i risultati vengono inseriti<br />

in un oggetto di tipo “NSMutableDictionary”: esso è come un grande contenitore, che ci<br />

<strong>per</strong>mette di inserire valori associandoci un tag (quello che facciamo alla riga 25).<br />

Come vedete non si tratta di o<strong>per</strong>azioni complesse, si tratta solo di capire come funziona il<br />

meccanismo, che potete poi variare a seconda delle vostre esigenze.<br />

Gli ultimi due metodi da inserire nel file “Data.m” sono i seguenti:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

+(void)finalizeStatements {<br />

! if(database)<br />

! ! sqlite3_close(database);<br />

}<br />

-(void)dealloc {<br />

! [lista release];<br />

! [su<strong>per</strong> dealloc];<br />

}<br />

Il primo si occupa di concludere la query e di chiudere la connessione al database (va sempre<br />

messo), mentre il secondo è il classico “dealloc”.<br />

Abbiamo concluso con la definizione della classe “Data”. Ora vedremo come creare il nostro<br />

database e inserirlo nel progetto.<br />

CREIAMO IL DATABASE<br />

Quello che dobbiamo andare a realizzare è un semplice database, con tecnologia SQLite. Per<br />

crearlo utilizzeremo un plug-in <strong>per</strong> Firefox, chiamato” SQLite Manager”, che potete trovare a<br />

questo indirizzo (https://addons.mozilla.org/en-US/firefox/addon/5817). In alternativa esistono<br />

alcuni programmi dedicati, come SQLiteManager (http://www.sqlabs.com/sqlitemanager.php),<br />

che è, <strong>per</strong>ò, a pagamento.<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 114


Dopo aver installato l’estensione, andiamo in “Strumenti -> SQLite Manager”, si avvierà il tool<br />

che ci <strong>per</strong>metterà di creare il nostro database. Clicchiamo sull’icona del foglio bianco <strong>per</strong> creare<br />

un nuovo database:<br />

e inseriamo “<strong>per</strong>sone” come nome <strong>per</strong> il file:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 115


e scegliamo dove salvare il file (vi consiglio sulla Scrivania, così potrete recu<strong>per</strong>arlo subito in<br />

seguito).<br />

Abbiamo così creato il nostro database, che risulta <strong>per</strong>ò essere completamente vuoto. Dobbiamo,<br />

quindi, creare la tabella “Persone”. Per fare ciò, facciamo clic con il tasto destro su “Tables”<br />

che trovate nella parte sinistra della schermata, e selezioniamo “Create Table”:<br />

Si aprirà una nuova schermata, in cui dovrete definire gli attributi della tabella. Ecco cosa dovete<br />

inserire:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 116


e clicchiamo poi su “Yes” nel messaggio successivo che apparirà.<br />

Abbiamo inserito gli attributi necessari, ovvero nome, cognome e un identificativo univoco<br />

(id).<br />

Non ci resta che inserire dei valori nella tabella. Per fare ciò, andate nella sezione “Execute<br />

SQL” inserite le seguenti istruzioni:<br />

INSERT INTO PERSONA (id,Nome,Cognome) VALUES ('1','Giovanni','Verdi');<br />

INSERT INTO PERSONA (id,Nome,Cognome) VALUES ('2','Paolo','Rossi');<br />

INSERT INTO PERSONA (id,Nome,Cognome) VALUES ('3','Luca','Bianchi');<br />

INSERT INTO PERSONA (id,Nome,Cognome) VALUES ('4','Andrea','Busi');<br />

Un messaggio in “Last Error” vi comunicherà se vi sono stati errori nell’inserimento dei dati,<br />

oppure se tutto è andato <strong>per</strong> il verso giusto.<br />

Possiamo, infine, controllare i valori che abbiamo inserito, spostandoci nella sezione “Browse<br />

& Search”:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 117


Abbiamo concluso! Chiudiamo pure il programmino, i cambiamenti sono già stati apportati al<br />

nostro database.<br />

CONCLUDIAMO L’APPLICAZIONE<br />

Torniamo ora ad XCode, e concludiamo lo sviluppo della nostra applicazione. Per prima cosa,<br />

dobbiamo inserire il database che abbiamo creato nel nostro progetto. Trasciniamo il file all’interno<br />

di XCode:<br />

e nella schermata che apparirà inserite la spunta a “Copy items into destination group’s folder”<br />

e cliccate su “Add”<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 118


Siamo pronti <strong>per</strong> completare la nostra applicazione. Iniziamo aprendo il file<br />

“RootViewController.h” e inseriamo il seguente codice:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

#import "Data.h"<br />

@interface RootViewController : UITableViewController {<br />

! // Oggetto con la lista degli elementi letti dal db<br />

! Data *dataList;<br />

}<br />

@end<br />

Alla riga 5 abbiamo dichiarato la lista che conterrà gli elementi letti dal database. Per capirci, è<br />

quella che viene creata dal metodo “caricaValoriDaDB”, che abbiamo definito in precedenza.<br />

Passiamo ora al file “RootViewController.m”. Iniziamo con il metodo “viewDidLoad”, che, come<br />

ormai dovreste sa<strong>per</strong>e, ci consente di eseguire delle o<strong>per</strong>azioni al caricamento dell’applicazione.<br />

Ecco come dovete modificare tale metodo:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

- (void)viewDidLoad {<br />

[su<strong>per</strong> viewDidLoad];<br />

! self.title = @"Lista Autori";<br />

! //leggiamo il path del database<br />

! NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath]<br />

stringByAppendingPathComponent:@"<strong>per</strong>sone.sqlite"];<br />

!<br />

! //creiamo la lista degli autori<br />

! dataList = [[Data alloc] init:defaultDBPath];<br />

}<br />

Alla riga 4 impostiamo il titolo alla nostra tabella, mentre alla riga 6 definiamo il <strong>per</strong>corso del<br />

nostro database. A prima vista può sembrare complessa, ma essa non fa altro che rilevare il <strong>per</strong>corso<br />

in cui si trova l’applicazione (sia essa su <strong>iPhone</strong> Simulator che su <strong>iPhone</strong> fisico) e aggiungere<br />

a tale <strong>per</strong>corso “<strong>per</strong>sone.sqlite”, che è proprio il database che abbiamo inserito nel nostro<br />

progetto.<br />

Alla riga 9, infine, inizializiamo la lista, passando alla funzione “init” proprio il <strong>per</strong>corso che<br />

abbiamo definito poche righe sopra.<br />

Dobbiamo, ora, definire i metodi necessari <strong>per</strong> settare la tabella. Abbiamo già visto questi metodi<br />

nei tutorial dedicati alle TableView, quindi non mi soffermerò troppo sulla spiegazione.<br />

Sempre all’interno del file “RootViewController.m”, scorretelo verso il fondo, e troverete i metodi<br />

del protocollo UITableView, che dovrete completare nel seguente modo:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 119


1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

12<br />

13<br />

14<br />

15<br />

16<br />

17<br />

18<br />

19<br />

20<br />

21<br />

22<br />

23<br />

24<br />

25<br />

26<br />

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {<br />

return 1;<br />

}<br />

// Customize the number of rows in the table view.<br />

- (NSInteger)tableView:(UITableView *)tableView<br />

numberOfRowsInSection:(NSInteger)section {<br />

return [dataList getSize];<br />

}<br />

// Customize the appearance of table view cells.<br />

- (UITableViewCell *)tableView:(UITableView *)tableView<br />

cellForRowAtIndexPath:(NSIndexPath *)indexPath {<br />

static NSString *CellIdentifier = @"Cell";<br />

UITableViewCell *cell = [tableView<br />

dequeueReusableCellWithIdentifier:CellIdentifier];<br />

if (cell == nil) {<br />

cell = [[[UITableViewCell alloc]<br />

initWithStyle:UITableViewCellStyleDefault<br />

reuseIdentifier:CellIdentifier] autorelease];<br />

}<br />

!<br />

! NSDictionary *itemAtIndex = (NSDictionary *)[dataList<br />

objectAtIndex:indexPath.row];<br />

! cell.textLabel.text = [itemAtIndex objectForKey:@"nome"];<br />

}<br />

return cell;<br />

I tre metodi sono i soliti che vanno inseriti quando si lavora con le UITableView. Concentriamoci<br />

un attimo sulle righe 22 e 23. Esse hanno il compito di ricavare un oggetto dalla lista “dataLista”<br />

(che contiene tutti i valori letti da database), <strong>per</strong> estrarne poi il nome desiderato (ovviamente<br />

vengono estratti tutti i nomi, dal primo all’ultimo). Potete vedere che dall’oggetto<br />

“itemAtIndex” viene estratto solo il nome: potremmo creare anche altre combinazioni, ad<br />

esempio con il cognome. Per fare ciò vi basterà modificare la riga 23 ad esempio nel seguente<br />

modo:<br />

1 [itemAtIndex objectForKey:@"cognome"];<br />

Abbiamo concluso la nostra applicazione! Clicchiamo su “Build and Go!” e controlliamo che<br />

funzioni tutto in maniera corretta.<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 120


<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 121


Parte 2:<br />

semplici applicazioni<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 122


Capitolo 14: Creiamo un semplice lettore di feed RSS<br />

In questa prima applicazione realizzeremo un semplice ma utilissimo lettore di feed RSS. Vedremo,<br />

infatti, come leggere i dati (solitamente degli articoli) di un feed, visualizzandoli in una<br />

tabella.<br />

Per realizzare questo semplice lettore di feed RSS utilizzeremo due aspetti che abbiamo già<br />

visto nei precedenti capitoli: la gestione delle tabelle (capitolo 9) e l’utilizzo di XML (capitolo<br />

12). Gli elementi relativi a questi due aspetti, quindi, non verranno più spiegati in questo capitolo,<br />

ma verranno considerati come già appresi dal lettore. Ci concentreremo, quindi, solo sugli<br />

elementi di rilievo <strong>per</strong> il lettore di feed RSS.<br />

CREIAMO UN NUOVO PROGETTO<br />

Iniziamo creando un nuovo progetto di tipo “Navigation-based Application” e chiamiamolo<br />

“SimpleRSSReader”. Abbiamo così creato il nostro nuovo progetto, che ci fornisce già una<br />

struttura a tabella, ottima <strong>per</strong> il nostro scopo.<br />

Solitamente la prima cosa che facciamo è realizzare la struttura grafica dell’applicazione. Oggi,<br />

<strong>per</strong>ò, non sarà necessario, in quanto XCode ci fornisce già un template predisposto, contenente<br />

una tabella che conterrà gli elementi che andremo a leggere.<br />

Il primo file che andremo a modificare è “RootViewController.h”. Apritelo e, al suo interno,<br />

scrivete il seguente codice:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

12<br />

13<br />

14<br />

15<br />

16<br />

17<br />

@interface RootViewController : UITableViewController {<br />

! // parser XML<br />

! NSXMLParser *rssParser;<br />

! // elenco degli elementi letti dal feed<br />

! NSMutableArray *elencoFeed;<br />

!<br />

! //variabile temporanea <strong>per</strong> ogni elemento<br />

! NSMutableDictionary *item;<br />

!<br />

! // valori dei campi letti dal feed<br />

! NSString *currentElement;<br />

! NSMutableString *currentTitle, *currentDate, *currentSummary,<br />

*currentLink;<br />

}<br />

- (void)parseXMLFileAtURL:(NSString *)URL;<br />

@end<br />

Alla riga 3 abbiamo definito il nostro parser XML, che si occu<strong>per</strong>à di leggere il feed RSS e di<br />

convertirne gli elementi. Alla riga 5 è definito un NSMutableArray, ovvero una collezione di<br />

oggetti, in cui inseriremo i vari feed letti (con le varie informazioni, ovvero titolo, data, testo,<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 123


etc). Le dichiarazioni alle righe 8, 11 e 12 servono proprio <strong>per</strong> i metodi del parser, sono i valori<br />

che vengono letti e che devono essere inseriti in un unico elemento (“item”), che andrà poi a<br />

comporre la lista degli elementi letti (“elencoFeed”).<br />

Apriamo, ora, il file “RootViewController.m”, in cui troverete già i metodi necessari <strong>per</strong> la definizione<br />

della tabella. Iniziamo a modificare i metodi già presenti, modificandoli a seconda<br />

delle nostre necessità.<br />

Il primo metodo da modificare è il seguente:<br />

1<br />

2<br />

3<br />

- (NSInteger)tableView:(UITableView *)tableView<br />

numberOfRowsInSection:(NSInteger)section {<br />

return [elencoFeed count];<br />

}<br />

Come già sapete, questo metodo imposta il numero di righe della nostra tabella. Tale numero<br />

deve essere pari al numero di elementi che scarichiamo dal feed RSS. Ad esempio, se abbiamo<br />

ricavato 10 notizie dal nostro feed, dovranno essere 10 le righe della tabella, ovvio vero?<br />

Dobbiamo ora modificare il metodo che si occupa di inserire il testo all’interno delle varie celle.<br />

Ecco il metodo che si occupa di ciò:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

12<br />

13<br />

14<br />

- (UITableViewCell *)tableView:(UITableView *)tableView<br />

cellForRowAtIndexPath:(NSIndexPath *)indexPath {<br />

static NSString *CellIdentifier = @"Cell";<br />

UITableViewCell *cell = [tableView<br />

dequeueReusableCellWithIdentifier:CellIdentifier];<br />

if (cell == nil) {<br />

cell = [[[UITableViewCell alloc]<br />

initWithStyle:UITableViewCellStyleDefault<br />

reuseIdentifier:CellIdentifier] autorelease];<br />

}<br />

!<br />

! // Configure the cell.<br />

! cell.textLabel.text = [[elencoFeed objectAtIndex:indexPath.row]<br />

objectForKey:@"title"];<br />

!<br />

! return cell;<br />

}<br />

Troverete anche questo metodo già definito, dovrete solo aggiungere l’istruzione alla riga 11.<br />

Tale istruzione va a ricavare l’elemento desiderato dalla lista (che coincide con il numero di riga,<br />

ricavato da “indexPath.row”), estrae il campo “title” (ovvero il titolo di ogni singolo elemento<br />

del feed RSS che avremo scaricato) e lo setta come contenuto della cella.<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 124


Se provassimo ad eseguire il programma adesso, vedremmo che non farebbe ancora niente.<br />

Non abbiamo, infatti, ancora aggiunto la possibilità di scaricare il feed e di utilizzarlo. Quindi<br />

ora facciamo proprio questo.<br />

DEFINIAMO LE AZIONI DEL PARSER<br />

Ci siamo occupati, fino ad ora, solo della definizione della tabella. Non abbiamo ancora visto<br />

nessun aspetto relativo al parser XML.<br />

Iniziamo, quindi, dal metodo “viewDidLoad” (lo trovate commentato nelle prime righe della<br />

classe):<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

- (void)viewDidLoad {<br />

[su<strong>per</strong> viewDidLoad];<br />

! self.title = @"BubiDevs";<br />

!<br />

! NSString *path = @"http://feeds.feedburner.com/TheBubiDevs";<br />

! [self parseXMLFileAtURL:path];<br />

!<br />

// Uncomment the following line to display an Edit button in the<br />

navigation bar for this view controller.<br />

// self.navigationItem.rightBarButtonItem = self.editButtonItem;<br />

}<br />

Come vedete abbiamo aggiunto alcune istruzioni. Alla riga 4 abbiamo settato un titolo alla nostra<br />

applicazione, che comparirà nella navigation bar sopra la tabella. Alla riga 6, invece, viene<br />

definita, una stringa “path”, in cui inseriamo l’indirizzo del feed RSS che vogliamo leggere. In<br />

questo caso io ho inserito l’indirizzo del feed del mio blog, BubiDevs, nulla vi vieta di inserire<br />

l’indirizzo del vostro feed preferito (s<strong>per</strong>iamo che sia uguale al mio! ;-) ). Alla riga successiva,<br />

infine, avviamo il parsing del feed (tramite il metodo “parseXMLFileAtURL”, di cui abbiamo<br />

definito l’intestazione nel file “RootViewController.h”), passando proprio l’indirizzo “path”<br />

come parametro.<br />

Tale metodo, <strong>per</strong>ò, non è ancora stato implementato nella nostra funzione. Ecco, quindi, come<br />

dovrete definirlo:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 125


1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

12<br />

13<br />

14<br />

15<br />

16<br />

17<br />

18<br />

19<br />

20<br />

- (void)parseXMLFileAtURL:(NSString *)URL {<br />

! // inizializziamo la lista degli elementi<br />

! elencoFeed = [[NSMutableArray alloc] init];<br />

!<br />

! // dobbiamo convertire la stringa "URL" in un elemento "NSURL"<br />

! NSURL *xmlURL = [NSURL URLWithString:URL];<br />

!<br />

! // inizializziamo il nostro parser XML<br />

! rssParser = [[NSXMLParser alloc] initWithContentsOfURL:xmlURL];<br />

!<br />

! [rssParser setDelegate:self];<br />

!<br />

! // settiamo alcune proprietà<br />

! [rssParser setShouldProcessNamespaces:NO];<br />

! [rssParser setShouldReportNamespacePrefixes:NO];<br />

! [rssParser setShouldResolveExternalEntities:NO];<br />

!<br />

! // avviamo il parsing del feed RSS<br />

! [rssParser parse];<br />

}<br />

Come vedete il metodo non è molto complicato. I commenti presenti vi possono chiarire le<br />

varie istruzioni. Si parte dall’inizializzazione dell’array “elencoFeed” (riga 3), <strong>per</strong> poi passare all’inizializzazione<br />

del parser XML (riga 6) e al suo avvio (riga 19).<br />

Per funzionare correttamente, il parser ha bisogno di altri due metodi. Eccoveli (anche questi<br />

sono da inserire in “RootViewController.m”):<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 126


1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

12<br />

13<br />

14<br />

15<br />

16<br />

17<br />

18<br />

19<br />

20<br />

21<br />

22<br />

23<br />

24<br />

25<br />

26<br />

27<br />

28<br />

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName<br />

namespaceURI:(NSString *)namespaceURI<br />

qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{!<br />

! !<br />

! currentElement = [elementName copy];<br />

! if ([elementName isEqualToString:@"item"]) {<br />

! ! // inizializza tutti gli elementi<br />

! ! item = [[NSMutableDictionary alloc] init];<br />

! ! currentTitle = [[NSMutableString alloc] init];<br />

! ! currentDate = [[NSMutableString alloc] init];<br />

! ! currentSummary = [[NSMutableString alloc] init];<br />

! ! currentLink = [[NSMutableString alloc] init];<br />

! }<br />

}<br />

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName<br />

namespaceURI:(NSString *)namespaceURI<br />

qualifiedName:(NSString *)qName{<br />

!<br />

! if ([elementName isEqualToString:@"item"]) {<br />

! ! /* salva tutte le proprietà del feed letto nell'elemento<br />

"item", <strong>per</strong><br />

! ! poi inserirlo nell'array "elencoFeed" */<br />

! ! [item setObject:currentTitle forKey:@"title"];<br />

! ! [item setObject:currentLink forKey:@"link"];<br />

! ! [item setObject:currentSummary forKey:@"summary"];<br />

! ! [item setObject:currentDate forKey:@"date"];<br />

! !<br />

! ! [elencoFeed addObject:[item copy]];<br />

! }<br />

}<br />

Questi due metodi vengono richiamati, rispettivamente, quando inizia e quando finisce un<br />

elemento XML. Nel primo caso dovremo re-inizializzare tutti gli elementi, in modo da poter<br />

leggere un nuovo elemento senza errori. Al contrario, quando un elemento XML termina dovremo<br />

salvare tutti questi valori letti in un unico elemento (“item”) e inserirlo nella lista dei<br />

feed letti (“elencoFeed”).<br />

Per completare la definizione del parser ci mancano solo due metodi:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 127


1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

12<br />

13<br />

14<br />

15<br />

16<br />

17<br />

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString<br />

*)string{;<br />

! // salva i caratteri <strong>per</strong> l'elemento corrente<br />

! if ([currentElement isEqualToString:@"title"]){<br />

! ! [currentTitle appendString:string];<br />

! } else if ([currentElement isEqualToString:@"link"]) {<br />

! ! [currentLink appendString:string];<br />

! } else if ([currentElement isEqualToString:@"description"]) {<br />

! ! [currentSummary appendString:string];<br />

! } else if ([currentElement isEqualToString:@"pubDate"]) {<br />

! ! [currentDate appendString:string];<br />

! }<br />

}<br />

- (void) parserDidEndDocument:(NSXMLParser *)parser {<br />

! [self.tableView reloadData];<br />

}<br />

Il primo metodo viene richiamato ogni volta che viene letto un carattere all’interno del feed. A<br />

seconda dell’elemento che siamo considerando, andremo a inserire il carattere letto in coda a<br />

quelli già letti dello stesso carattere, in modo da ricostruire l’informazione completa. Ad esempio,<br />

stiamo considerando l’elemento “title”. Vengono letti, nell’ordine, i seguenti caratteri<br />

“Dev”, “<strong>Tutorial</strong> “, “#2ʺ″. Unendo i vari caratteri letti ricostruiremo il titolo esatto del nostro<br />

feed, ovvero “Dev<strong>Tutorial</strong> #2ʺ″.<br />

Il secondo metodo, invece, viene richiamato solo quando il parser completa la lettura del feed<br />

RSS, e noi non faremo altro che dire alla tabella di ricarcarsi (verranno, quindi, richiamati i metodi<br />

<strong>per</strong> settare il numero di righe e <strong>per</strong> inserire il testo nelle varie celle).<br />

CONCLUDIAMO L’APPLICAZIONE<br />

Abbiamo ormai concluso la nostra applicazione!!<br />

Come sempre dobbiamo ricordarci di completare il metodo “dealloc”, che è davvero molto importante,<br />

soprattutto nelle applicazioni di un certo grado di complessità. Ecco come dovrete<br />

definire il metodo:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

12<br />

- (void)dealloc {<br />

! [currentElement release];<br />

! [rssParser release];<br />

! [elencoFeed release];<br />

! [item release];<br />

! [currentTitle release];<br />

! [currentDate release];<br />

! [currentSummary release];<br />

! [currentLink release];<br />

!<br />

[su<strong>per</strong> dealloc];<br />

}<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 128


Ora siamo pronti <strong>per</strong> compilare ed eseguire la nostra applicazione! Cliccate su “Build and Run!”<br />

e testare il vostro <strong>per</strong>sonalissimo lettore di feed RSS!!<br />

UN PICCOLO MIGLIORAMENTO<br />

La nostra applicazione funziona ma.. provate a cliccare su un elemento. Non succederà niente.<br />

Non sarebbe invece più carino se si aprisse la pagina in Safari che ci <strong>per</strong>metta di leggere l’intera<br />

notizia?<br />

È presto fatto! Sempre all’interno di “RootViewController.m” cercate il metodo “tableView:<br />

didSelectRowAtIndexPath:” (è uno di quelli commentati di cui vi avevo accennato prima).<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 129


Questo metodo viene richiamato ogni volta che si “clicca” su una cella. Sarà qui che andremo<br />

ad inserire il codice necessario:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

12<br />

13<br />

- (void)tableView:(UITableView *)tableView<br />

didSelectRowAtIndexPath:(NSIndexPath *)indexPath {<br />

! // ricaviamo il link dell'elemento selezionato<br />

! NSString *link = [[elencoFeed objectAtIndex:indexPath.row] objectForKey:<br />

@"link"];<br />

!<br />

! // ripuliamo il link da spazi, return e tabs<br />

! link = [link stringByReplacingOccurrencesOfString:@" "<br />

withString:@""];<br />

! link = [link stringByReplacingOccurrencesOfString:@"\n"<br />

withString:@""];<br />

! link = [link stringByReplacingOccurrencesOfString:@"! "<br />

withString:@""];<br />

!<br />

! // apriamo la notizia in Safari<br />

! [[UIApplication sharedApplication] openURL:[NSURL<br />

URLWithString:link]];<br />

}<br />

Il procedimento è molto simile a quello visto <strong>per</strong> la definizione delle celle della tabella. Alla riga<br />

4, infatti, andiamo a ricavare la proprietà “link” dell’elemento selezionato, associandola ad<br />

una stringa chiamata appunto “link”. Con le istruzioni seguenti, invece, ripuliamo l’indirizzo da<br />

eventuali caratteri indesiderati, come spazi, return o tab. Con l’istruzione alla riga 12, infine,<br />

apriamo Safari passandogli come parametro proprio il link da noi voluto (che deve essere trasformato<br />

in un NSURL). Fatto!<br />

Salvate il tutto, cliccate su “Build and Run” e godetevi la vostra bellissima applicazione!!<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 130


<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 131


Capitolo 15: Creiamo un client <strong>per</strong> Twitter!<br />

Attenzione: recentemente Twitter ha cambiato le modalità di accesso, abbandonando le API<br />

che vengono sfruttate in questo tutorial. Ne deriva, quindi, che questa guida non funziona correttamente,<br />

in quanto l’applicazione non riesce a leggere i dati da Twitter. Sono già al lavoro<br />

<strong>per</strong> cercare di sistemare questo problema, s<strong>per</strong>o di poter aggiornare la guida in tempi brevi.<br />

Dopo aver creato un semplice lettore di feed RSS, complichiamo un po’ le cose. In questo capitolo<br />

realizzeremo un nostro <strong>per</strong>sonalissimo client <strong>per</strong> Twitter, uno dei social network di maggior<br />

successo dell’ultimo <strong>per</strong>iodo (io lo trovo molto utile).<br />

Nella realizzazione di questa applicazione vedremo vari aspetti diversi. Utilizzeremo, infatti,<br />

una classe che ho trovato su Internet: MGTwitterEngine (link del sito originale), che ci <strong>per</strong>metterà<br />

di interagire in maniera facile e veloce con Twitter. Analizzeremo, poi, altri due aspetti<br />

molto importanti: le UITableViewCe", ovvero le celle <strong>per</strong>sonalizzate <strong>per</strong> le UITableView e la<br />

classe NSUserDefault, che ci <strong>per</strong>metterà di salvare i dati della nostra applicazione.<br />

PARTE 1: CONNETTIAMOCI A TWITTER<br />

Nella prima parte del tutorial vedremo come connetterci a Twitter utilizzando la classe<br />

MGTwitterEngine che abbiamo già nominato più volte. Leggeremo, poi, tutta la nostra timeline<br />

e la salveremo all’interno di una struttura dati che creeremo appositamente.<br />

IMPOSTIAMO LA LIBRERIA “MGTWITTERENGINE”<br />

Iniziamo creando un nuovo progetto di tipo “View-based application” e chiamiamolo “SampleTwitterClient”.<br />

Prima di fare qualsiasi altra cosa, dobbiamo inserire la libreria MGTwitterEngine, che ci<br />

<strong>per</strong>metterà di interagire con Twitter. Scaricate l’ultima versione da questa repository SVN (trovate<br />

qui una mia guida su come fare), oppure scarica la versione 1.08 che vi mettiamo noi a disposizione<br />

(la trovate anche nei codici sorgenti forniti insieme a questo libro).<br />

Estraiamo l’archivio ed apriamo il file “MGTwitterEngine.xcodeproj”, un progetto esempio<br />

fornito dai creatori della classe, che potete guardare <strong>per</strong> avere una panoramica della libreria. La<br />

procedura da seguire è spiegata nel file “README.txt” di questo progetto, ma vi illustrerò tutti<br />

i passaggi in modo che non abbiate problemi di alcun genere.<br />

A noi interessa la cartella “MATwitterEngine” che trovate all’interno di “Classes”:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 132


Prendetela e trascinatela all’interno del nostro progetto “SimpleTwitterClient” che abbiamo<br />

creato poco fa:<br />

e cliccate su “Add” nella schermata che vi apparirà appena rilascerete la cartella, ricordandovi di<br />

mettere il segno di spunta nell’opzione in alto.<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 133


Possiamo chiudere il progetto “MGTwitterEngine” e tornare al nostro “SampleTwitterClient”.<br />

Importiamo, ora, il framework che si dovrà occupare del parsing XML. Clicchiamo con il tasto<br />

destro sulla cartella “Frameworks” e scegliamo “Add” -> “Existing Frameworks…”:<br />

Dall’elenco che appare selezioniamo poi “libxml2.dylib” e clicchiamo su “Add”.<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 134


Abbiamo così importato il framework necessario.<br />

Ci manca solo un’o<strong>per</strong>azione <strong>per</strong> fare in modo che la libreria “MGTwitterEngine” funzioni alla<br />

<strong>per</strong>fezione. Facciamo doppio clic sul nome del progetto <strong>per</strong> aprirne le proprietà. Nella sezione<br />

“Build” cerchiamo la voce “Header Search Path”:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 135


facciamo doppio clic su tale voce e quando si apre inseriamoci la stringa “$<strong>SDK</strong>ROOT/usr/include/libxml2ʺ″<br />

(ci basterà cliccare sul bottoncino “+”):<br />

Clicchiamo infine su “OK”. Abbiamo concluso la fase iniziale di creazione del nostro progetto.<br />

DEFINIAMO LA VISTA DI CARICAMENTO<br />

XCode ha già creato <strong>per</strong> noi una vista, “SampleTwitterClientViewController.xib”. Questa verrà<br />

caricata all’avvio dell’applicazione, sarà quindi qui che andremo a leggere la nostra timeline di<br />

Twitter. Prima di fare ciò, creiamo un semplice aspetto grafico <strong>per</strong> questa vista.<br />

Aprite il file “SampleTwitterClientViewController.xib” e modificatelo a vostro piacere. Io l’ho<br />

impostato così:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 136


L’unico componente di rilievo è il componente “UIActivityIndicatorView” posto sotto la label<br />

“Caricamento in corso...”, che utilizzeremo <strong>per</strong> far capire all’utente che l’applicazione sta caricando<br />

i dati e non è bloccata.<br />

Salvate il file e chiudete pure Interface Builder.<br />

CREIAMO LA CLASSE “TWEET”<br />

Come abbiamo già detto, la nostra applicazione andrà a leggere la timeline del nostro account<br />

di Twitter. Dobbiamo creare una classe, quindi, in grado di ospitare le informazioni di ogni singolo<br />

tweet letto. Per semplicità, ci limiteremo a salvare solo alcuni dati di ogni tweet: il nome<br />

dell’utente che ha “cinguettato”, la sua immagine del profilo e il testo del tweet.<br />

Facciamo clic con il tasto destro su “Classes” e clicchiamo poi su “Add” -> “New File…”. Creiamo<br />

poi una classe del tipo “Objective-C class”, e chiamiamola “Tweet”. Vediamo di definire le<br />

variabili e i metodi di questa classe.<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 137


Nel file “Tweet.h” inseriamo il seguente codice:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

12<br />

13<br />

#import <br />

@interface Tweet : NSObject {<br />

! NSString *testo;<br />

! NSString *user;<br />

! UIImage *immagine;<br />

}<br />

@pro<strong>per</strong>ty (nonatomic, retain) NSString *testo;<br />

@pro<strong>per</strong>ty (nonatomic, retain) NSString *user;<br />

@pro<strong>per</strong>ty (nonatomic, retain) UIImage *immagine;<br />

@end<br />

Abbiamo dichiarato tre elementi, come vi ho anticipato poco fa:<br />

1. testo, che conterrà il messaggio del tweet, il testo appunto;<br />

2. user, che conterrà l’username di chi ha inserito il tweet letto;<br />

3. immagine, è l’immmagine (l’avatar) dell’utente che ha lasciato il tweet.<br />

Niente di complicato quindi. Nel file “Tweet.m” dovrete solo implementare il metodo “dealloc”<br />

e inserire “@synthesize”:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

12<br />

13<br />

14<br />

15<br />

#import "Tweet.h"<br />

@implementation Tweet<br />

@synthesize testo, user, immagine;<br />

-(void)dealloc{<br />

! [testo release];<br />

! [user release];<br />

! [immagine release];<br />

! [su<strong>per</strong> dealloc];<br />

}<br />

@end<br />

Ovviamente se intendete creare un client più complesso potrete aumentare i componenti di<br />

questa classe, oppure inserire dei metodi che eseguano qualche o<strong>per</strong>azione (ad esempio un controllo<br />

dei dati). Per questo tutorial, tuttavia, ci basteranno questi semplici elementi.<br />

DEFINIAMO LA CLASSE “SAMPLETWITTERCLIENTVIEWCON-<br />

TROLLER”<br />

È venuto finalmente il momento di implementare la classe che si occu<strong>per</strong>à di leggere la timeline<br />

di Twitter.<br />

Apriamo il file “SampleTwitterClientViewController.h” e inseriamo il seguente codice:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 138


1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

12<br />

13<br />

14<br />

15<br />

16<br />

17<br />

18<br />

19<br />

20<br />

#import <br />

#import "MGTwitterEngine.h"<br />

@class Tweet;<br />

@interface SampleTwitterClientViewController : UIViewController<br />

{<br />

! MGTwitterEngine *twitterEngine;<br />

! NSMutableArray *listaTweet;<br />

!<br />

! IBOutlet UIActivityIndicatorView *spinner;<br />

}<br />

-(NSString*)getMessaggio:(NSDictionary*)element;<br />

-(NSString*)getUser:(NSDictionary*)element;<br />

-(NSURL*)getUrlImage:(NSDictionary*)element;<br />

@pro<strong>per</strong>ty (nonatomic, retain) NSMutableArray *listaTweet;<br />

@pro<strong>per</strong>ty (nonatomic, retain) IBOutlet UIActivityIndicatorView<br />

*spinner;<br />

@end<br />

Alla riga 7 abbiamo definito un elemento di tipo “MGTwitterEngine”, proprio quello della classe<br />

che abbiamo inserito all’inizio del tutorial. Sarà questo componente che si occu<strong>per</strong>à della<br />

connessione con Twitter e della lettura della nostra timeline. Nell’intestazione (riga 6) abbiamo<br />

anche inserito il protocollo di questa classe, che ci “obbliga” così ad implementare dei metodi<br />

che vedremo in seguito.<br />

L’array dichiarato alla riga 8 conterrà vari elementi del tipo “Tweet”, ognuno dei quali conterrà<br />

un tweet letto dal nostro account. Sarà, quindi, una lista che conterrà tutti i tweet della nostra<br />

timeline.<br />

La riga 10, invece, contiene la definizione della “spinning wheel”, ovvero la classica “rotella che<br />

gira”, l’UIActivityIndicatorView che abbiamo inserito in precedenza nella vista (e che collegheremo<br />

fra poco in IB).<br />

Ci sono poi 3 metodi getter (“getMessaggio”, “getUser” e “getUrlImage”) che avranno il compito<br />

di ricavare il campo desiderato, partendo dall’NSDictionary che ricevono in input, e di salvare<br />

le varie informazioni di ogni singolo tweet.<br />

Salviamo la classe e, prima di continuare l’implementazione, apriamo nuovamente il file<br />

“SampleTwitterClientViewController.xib”, in cui dovremo collegare l’elemento “UIActivityIndicatorView”<br />

che abbiamo appena definito con quello che abbiamo inserito in IB.<br />

Dal Pannello dei Documenti clicchiamo sul “File’s Owner” e andiamo poi nel “Connections<br />

Inspector”. Colleghiamo l’elemento “spinner” con il componente grafico “UIActivityIndicatorView”<br />

che abbiamo inserito in precedenza. Se abbiamo eseguito tutto correttamente avrete<br />

il seguente risultato:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 139


Possiamo salvare e chiudere Interface Builder<br />

LEGGIAMO LA TIMELINE<br />

Iniziamo ad implementare il codice che deve leggere i tweet dalla nostra timeline. Apriamo il<br />

file “SampleTwitterClientViewController.m” ed inseriamo il seguente codice:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

12<br />

13<br />

14<br />

15<br />

16<br />

17<br />

18<br />

19<br />

20<br />

21<br />

22<br />

#import "SampleTwitterClientViewController.h"<br />

#import "Tweet.h"<br />

@implementation SampleTwitterClientViewController<br />

@synthesize listaTweet, spinner;<br />

-(void)viewDidLoad{<br />

!<br />

! // Username e password <strong>per</strong> accedere a Twitter<br />

NSString *username = @"user_name";<br />

NSString *password = @"password";<br />

// Create a TwitterEngine and set our login details.<br />

twitterEngine = [[MGTwitterEngine alloc] initWithDelegate:self];<br />

[twitterEngine setUsername:username password:password];<br />

// <strong>Get</strong> updates from people the authenticated user follows.<br />

[twitterEngine getFollowedTimelineFor:username since:nil<br />

startingAtPage:0];<br />

! !<br />

! [spinner startAnimating];<br />

}<br />

Non preoccupatevi troppo di capire il codice, in quanto l’ho preso direttamente dall’esempio<br />

fornito con la classe “MGTwitterEngine”. Ricordatevi, comunque, di inserire i vostro dati <strong>per</strong> il<br />

login alla riga 11 e 12. Le righe seguenti, invece, servono <strong>per</strong> inizializzare l’elemento “twitterEngine”,<br />

che si occu<strong>per</strong>à di leggere la timeline di Twitter.<br />

Alla riga 21, inoltre, abbiamo avviato la rotella (che fermeremo quando la procedura di lettura e<br />

conversione dei dati sarà terminata).<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 140


Nota: se invece di leggere la vostra timeline vorreste leggere i messaggi di un utente (non la<br />

sua timeline, solo i suoi tweet) dovete sostituire l’istruzione alla riga 19 con la seguente:<br />

1 [twitterEngine getUserTimelineFor:username sinceID:nil<br />

startingAtPage:0 count:5];<br />

Inseriamo, ora, dei metodi obbligatori da inserire, in quanto parte del delegato “MGTwitterEngineDelegate”.<br />

Eccoli:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

12<br />

13<br />

14<br />

15<br />

16<br />

17<br />

18<br />

19<br />

20<br />

21<br />

22<br />

23<br />

24<br />

- (void)requestSucceeded:(NSString *)requestIdentifier{<br />

NSLog(@"Request succeeded (%@)", requestIdentifier);<br />

}<br />

- (void)requestFailed:(NSString *)requestIdentifier<br />

withError:(NSError *)error{<br />

NSLog(@"Twitter request failed! (%@) Error: %@ (%@)", requestIdentifier,<br />

[error localizedDescription],<br />

[[error userInfo] objectForKey:NSErrorFailingURLStringKey]);<br />

! [spinner stopAnimating];<br />

! UIAlertView *alert = [[UIAlertView alloc]<br />

initWithTitle:@"Errore!"<br />

message:@"Connessione non riuscita.\nControlla i dati d'accesso"<br />

delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];<br />

! [alert show];<br />

! [alert release];<br />

}<br />

- (void)directMessagesReceived:(NSArray *)messages<br />

forRequest:(NSString *)identifier{<br />

NSLog(@"Got direct messages:\r%@", messages);<br />

}<br />

- (void)userInfoReceived:(NSArray *)userInfo forRequest:(NSString<br />

*)identifier{<br />

NSLog(@"Got user info:\r%@", userInfo);<br />

}<br />

- (void)miscInfoReceived:(NSArray *)miscInfo forRequest:(NSString<br />

*)identifier{<br />

! NSLog(@"Got misc info:\r%@", miscInfo);<br />

}<br />

L’unico metodo a cui ho aggiunto un po’ di codice è il secondo, ovvero “requestFailed: withError:”.<br />

Questo è richiamato se la connessione con Twitter non è possibile, quindi avviamo una<br />

UIAlertView che lo comunica all’utente e fermiamo la rotella. Come messaggio comunichiamo<br />

che i dati d’accesso sono errati, in realtà dovremmo controllare il codice d’errore e inserire un<br />

messaggio a seconda dell’errore riscontrato (potrebbe non essere presente la connessione, oppure<br />

Twitter potrebbe essere down, o i dati inseriti potrebbero essere errati, etc).<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 141


Mancano solo pochi metodi <strong>per</strong> concludere questo primo tutorial. Ecco cosa dovete inserire<br />

ora:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

12<br />

13<br />

14<br />

15<br />

16<br />

17<br />

18<br />

19<br />

20<br />

21<br />

22<br />

23<br />

24<br />

25<br />

26<br />

27<br />

28<br />

29<br />

- (void)statusesReceived:(NSArray *)statuses forRequest:(NSString<br />

*)identifier{<br />

!<br />

! listaTweet = [[NSMutableArray alloc] init];<br />

! Tweet *elemento;<br />

!<br />

for (int i=0; i


molto semplice leggere le informazioni dei vari campi, vi basterà utilizzare il metodo “object-<br />

ForKey” e inserire l’attributo che volete leggere.<br />

Nota: il metodo “getUser” ci restituisce il nome completo dell’utente di cui abbiamo letto il<br />

messaggio. Se volete, invece, solo leggerne il nickname utilizzate questa istruzione (riga 23):<br />

1 return [[element objectForKey:@"user"] objectForKey:@"screen_name"];<br />

Quello che potrebbe sembrarvi più complicato è la lettura dell’immagine. Il metodo “getUrlImage”<br />

ci restituisce un elemento NSURL, che è l’indirizzo web dell’immagine dell’utente. Alla<br />

riga 10 creiamo, poi, un’immagine a partire dai dati letti a quell’indirizzo (XCode ci restituisce<br />

infatti un elemento NSData, che va convertito in UIImage). L’immagine convertita viene poi<br />

inserita nell’elemento corrente (ovviamente nel campo “immagine”).<br />

Alla fine del ciclo for avremo la “listaTweet” che conterrà n elementi di tipo Tweet, ognuno dei<br />

quali avrà le informazioni ricavate in precedenza. Proprio ciò che volevamo.<br />

Abbiamo così completato questa prima parte del tutorial!<br />

PARTE 2: CREIAMO LA TABELLA CON I TWEET LETTI<br />

In questa seconda parte vedremo come creare una tabella con le celle <strong>per</strong>sonalizzate, che dovrà<br />

visualizzare gli elementi Tweet che abbiamo salvato nella lista. Utilizzeremo, quindi, la classe<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 143


UITableViewCell <strong>per</strong> creare delle celle <strong>per</strong>sonalizzate, in modo da ottenere una tabella con<br />

un layout ad-hoc.<br />

Come prima cosa, andremo a creare la tabella che conterrà i tweet letti dalla nostra timeline.<br />

Iniziamo a creare, quindi, una tabella e la classe <strong>per</strong> gestirla.<br />

Andiamo “File” -> “New File…” e dalla sezione “Cocoa Touch Class” scegliamo “UIViewController<br />

subclass”, mettendo la spunta sulle opzioni “UITableViewController subclass” e “With<br />

XIB for user interface”.<br />

Facendo così avremo già un file “.xib” contenente una tabella e la classe associata, risparmiando<br />

tempo e lavoro.<br />

Se abbiamo creato tutto in modo corretto avremo i seguenti file nel nostro progetto (io li ho<br />

spostati <strong>per</strong> avere tutto ordinato):<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 144


Apriamo il file “tabellaTwitterViewController.xib”, dovremo fare una piccola modifica. Dal<br />

Pannello dei Documenti selezioniamo la “Table View” (ovvero la tabella) e apriamo poi il “Size<br />

Inspector”. Modifichiamo l’altezza delle celle, portando il valore a 70. Il campo da modificare è<br />

il seguente:<br />

Ovviamente potete dimensionare le celle a vostro piacimento, io ho ritenuto questa dimensione<br />

accettabile <strong>per</strong> la struttura che avevo in mente.<br />

Abbiamo così concluso la definizione grafica della tabella. Possiamo salvare e chiudere Interface<br />

Builder.<br />

CREIAMO LA CELLA PERSONALIZZATA<br />

Vediamo, ora, un’aspetto nuovo. Solitamente quando utilizziamo le tabelle ci limitiamo ad inserire<br />

del testo che sarà contenuto all’interno della cella. Per questo tutorial, invece, andremo a<br />

creare una nostra cella <strong>per</strong>sonalizzata, che comporrà poi la tabella.<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 145


Il procedimento non è difficile, <strong>per</strong>ò merita attenzione <strong>per</strong> non <strong>per</strong>dere nessun passaggio. Iniziamo<br />

creando un file xib vuoto (“File” -> “New File…” -> “Empty XIB”) e chiamiamolo “cellaTweet”.<br />

Facciamo doppio clic sul file appena creato <strong>per</strong> aprirlo in IB.<br />

Inseriamo all’interno della vista un componente di tipo “UITableViewCell”:<br />

Facciamo doppio clic sul componente che abbiamo appena inserito, si aprirà questa piccola vista:<br />

Questa è la base della nostra cella <strong>per</strong>sonalizzata. Fra poco inseriremo i componenti che conterranno<br />

poi le informazioni che desideriamo (che saranno, ovviamente, quelle che abbiamo<br />

fatto salvare nella prima parte del tutorial, quindi nome utente, testo del tweet e immagine dell’utente).<br />

Prima di fare ciò, andiamo nel “Size Inspector” e modifichiamo l’altezza a 70 (lo stesso<br />

valore che abbiamo impostato prima nella tabella, ricordate?):<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 146


Andiamo, poi, nell’”Attributes Inspector” e nel campo “Identifier” inseriamo “Cell”:<br />

Ora inseriamo gli elementi che dovranno comporre tutte le singole celle. Ci serviranno due<br />

UILabel e una UIImageView. Io le ho disposte e <strong>per</strong>sonalizzate come vedete di seguito, voi siete<br />

liberissimi di inserirle in maniera diversa!<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 147


Manca solo una piccola o<strong>per</strong>azione. Dobbiamo dare ai componenti un identificatore univoco,<br />

in modo che potremo, poi, selezionarli via codice in maniera molto veloce. Selezioniamo la<br />

UIImageView e andiamo nell’”Attributes Inspector”. Nel campo tag inseriamo il valore 0 (dovrebbe<br />

già essere presente):<br />

Facciamo la stessa o<strong>per</strong>azione con le due label, impostando <strong>per</strong> la label del nome utente il tag 1,<br />

mentre <strong>per</strong> la label che conterrà il testo del tweet il tag 2. Questa seconda label conterrà il testo<br />

dei tweet, quindi dobbiamo fare in modo che possa contenere più testo. Riduciamo le dimensioni<br />

del font e impostiamo il numero massimo di righe a 2:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 148


Abbiamo così concluso anche la definizione della cella <strong>per</strong>sonalizzata. Come vedete questo metodo<br />

è molto versatile, potrete <strong>per</strong>sonalizzare al massimo qualsiasi tabella!<br />

DEFINIAMO LA CLASSE DELLA TABELLA<br />

Dobbiamo ora iniziare a mettere mano al codice. Per prima cosa definiamo la tabella che mostrerà<br />

i tweet che abbiamo letto durante il caricamento dell’applicazione.<br />

Ecco il codice da inserire nel file “TabellaTwitterViewController.h”:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

12<br />

13<br />

#import <br />

@interface TabellaTwitterViewController : UITableViewController {<br />

! NSMutableArray *lista;<br />

! UITableViewCell *cellaNib;<br />

}<br />

@pro<strong>per</strong>ty (nonatomic, retain) NSMutableArray *lista;<br />

@pro<strong>per</strong>ty (nonatomic, retain) IBOutlet UITableViewCell *cellaNib;<br />

- (UIImage *)scale:(UIImage *)image toSize:(CGSize)size;<br />

@end<br />

Come vedete il codice rispecchia quello che solitamente è utilizzato <strong>per</strong> la gestione delle tabelle.<br />

Abbiamo definito una lista di elementi (alla riga 4), che corrisponderà a quella che abbiamo<br />

definito nella classe “SampleTwitterClientViewController”. L’elemento “cellaNib”, invece, cor-<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 149


isponderà alla cella che abbiamo creato poco fa in Interface Builder.<br />

Alla riga 11, infine, troviamo la definizione di un metodo “scale”, che ci <strong>per</strong>metterà di ridimensionare<br />

l’immagine <strong>per</strong> essere contenuta interamente nella UIImageView della cella <strong>per</strong>sonalizzata.<br />

Questo ci <strong>per</strong>metterà di non sprecare memoria inutilmente.<br />

Definiamo, ora, il contenuto del file “TabellaTwitterViewController.m”. Iniziamo inserendo le<br />

seguenti intestazioni:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

#import "TabellaTwitterViewController.h"<br />

#import "Tweet.h"<br />

@implementation TabellaTwitterViewController<br />

@synthesize lista, cellaNib;<br />

Modifichiamo, poi, il metodo “tableView: numberOfRowInSection:” impostando come valore<br />

di ritorno la dimensione della lista:<br />

1<br />

2<br />

3<br />

- (NSInteger)tableView:(UITableView *)tableView<br />

numberOfRowsInSection:(NSInteger)section {<br />

return [lista count];<br />

}<br />

Ora dobbiamo implementare il metodo “tableView: cellForRowAtIndexPath:”. È un po’ diverso<br />

dal solito, eccovelo:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

12<br />

13<br />

14<br />

15<br />

16<br />

17<br />

18<br />

19<br />

20<br />

21<br />

- (UITableViewCell *)tableView:(UITableView *)tableView<br />

cellForRowAtIndexPath:(NSIndexPath *)indexPath {<br />

static NSString *CellIdentifier = @"Cell";<br />

UITableViewCell *cell = [tableView<br />

dequeueReusableCellWithIdentifier:CellIdentifier];<br />

if (cell == nil) {<br />

! ! [[NSBundle mainBundle] loadNibNamed:@"cellaTweet"<br />

owner:self options:NULL];<br />

! ! cell = cellaNib;<br />

}<br />

!<br />

! Tweet *elemento = [lista objectAtIndex:indexPath.row];<br />

! UILabel *testoLabel = (UILabel*)[cell viewWithTag:2];<br />

! testoLabel.text = elemento.testo;<br />

! UILabel *userLabel = (UILabel*)[cell viewWithTag:1];<br />

! userLabel.text = elemento.user;<br />

!<br />

! UIImageView *immagine = (UIImageView*)[cell viewWithTag:3];<br />

! [immagine setImage:[self scale:elemento.immagine<br />

toSize:CGSizeMake(60, 60)]];<br />

!<br />

! return cell;<br />

}<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 150


Come potete vedere, l’inizializzazione della cella avviene in maniera diversa dal solito. Alla riga<br />

7, infatti, viene creata una nuova cella partendo dal file xib “cellaTweet”. Nelle istruzioni successive<br />

vengono invece settate le varie informazioni del tweet (nome utente, testo e immagine).<br />

Potete vedere che l’elemento della cella viene richiamato mediante il tag (con la funzione [cell<br />

viewWithTag:X]), ecco <strong>per</strong>chè prima lo abbiamo impostato in Interface Builder.<br />

L’imagine, inoltre, viene ridimensionata con la funzione “scale: toSize:”. Importante sono i valori<br />

che vengono passati nell’oggetto CGMakeSize (riga 18): essi sono le dimensioni a cui vogliamo<br />

ridimensionare le nostre immagini (devono corrispondere con le dimensioni che avete impostato<br />

alla UIImageView nella cella <strong>per</strong>sonalizzata).<br />

Ecco, quindi, la definizione del metodo che ridimensiona le immagini:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

- (UIImage *)scale:(UIImage *)image toSize:(CGSize)size{<br />

UIGraphicsBeginImageContext(size);<br />

[image drawInRect:CGRectMake(0, 0, size.width, size.height)];<br />

UIImage *scaledImage =<br />

UIGraphics<strong>Get</strong>ImageFromCurrentImageContext();<br />

UIGraphicsEndImageContext();<br />

return scaledImage;<br />

}<br />

Non commento questo metodo, in quanto l’ho trovato anche io su Internet, <strong>per</strong> la precisione a<br />

questo indirizzo. Ringrazio, quindi, il legittimo autore.<br />

La nostra tabella è completa!<br />

COMPLETIAMO L’APPLICAZIONE<br />

Ci mancano solo due cose <strong>per</strong> completare il nostro client.<br />

Per prima cosa, apriamo nuovamente il file “cellaTweet.xib”. Selezioniamo il “File’s Owner” ed<br />

entriamo nell’”Identity Inspector”. Impostiamo come classe della vista “TabellaTwitterView-<br />

Controller”:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 151


Spostiamoci, poi, nel pannello “Connections Inspector” e colleghiamo l’elemento “cellaNib” al<br />

componente UITableViewCell che avevamo in precedenza inserito. Se avete fatto in maniera<br />

corretta il collegamento avrete il seguente risultato:<br />

Salviamo e chiudiamo pure Interface Builder.<br />

Dobbiamo ora solo completare il caricamento dell’applicazione, che deve avviare la tabella dopo<br />

aver letto la nostra timeline. Torniamo, quindi, in “SampleTwitterClientViewController.h”.<br />

Dobbiamo definire un elemento “TabellaTwitterViewController”, in modo da poterlo richiamare<br />

alla fine del caricamento dei tweet, facendo così apparire la nostra tabella. Modifichiamo<br />

così il file “SampleTwitterClientViewController.h”:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 152


1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

12<br />

13<br />

14<br />

15<br />

16<br />

17<br />

18<br />

19<br />

20<br />

21<br />

22<br />

23<br />

24<br />

#import <br />

#import "MGTwitterEngine.h"<br />

@class Tweet;<br />

@class TabellaTwitterViewController;<br />

@interface SampleTwitterClientViewController : UIViewController<br />

{<br />

! MGTwitterEngine *twitterEngine;<br />

! NSMutableArray *listaTweet;<br />

!<br />

! IBOutlet UIActivityIndicatorView *spinner;<br />

!<br />

! TabellaTwitterViewController *tabellaTwitterViewController;<br />

}<br />

-(NSString*)getMessaggio:(NSDictionary*)element;<br />

-(NSString*)getUser:(NSDictionary*)element;<br />

-(NSURL*)getUrlImage:(NSDictionary*)element;<br />

@pro<strong>per</strong>ty (nonatomic, retain) NSMutableArray *listaTweet;<br />

@pro<strong>per</strong>ty (nonatomic, retain) IBOutlet UIActivityIndicatorView<br />

*spinner;<br />

@pro<strong>per</strong>ty (nonatomic, retain) IBOutlet TabellaTwitterViewController<br />

*tabellaTwitterViewController;<br />

@end<br />

Andiamo, poi, nel file “SampleTwitterClientViewController.m”. Modifichiamo le dichiarazioni<br />

e le importazioni nel seguente modo:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

#import "SampleTwitterClientViewController.h"<br />

#import "Tweet.h"<br />

#import "TabellaTwitterViewController.h"<br />

@implementation SampleTwitterClientViewController<br />

@synthesize listaTweet, spinner, tabellaTwitterViewController;<br />

Modifichiamo, ora, il metodo “statusesReceived: forRequest:”, inserendo il seguente codice alla<br />

fine di tale metodo:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

[elemento release];<br />

!<br />

self.tabellaTwitterViewController.lista = self.listaTweet;<br />

!<br />

[spinner stopAnimating];<br />

!<br />

[self presentModalViewController:self.tabellaTwitterViewController<br />

animated:YES];<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 153


Con queste poche righe abbiamo semplicemente impostato la lista degli elementi della nostra<br />

tabella, che corrisponderà alla lista dei tweet che abbiamo creato in precedenza (parte 1 del tutorial).<br />

Abbiamo quasi terminato! Dobbiamo impostare la gestione di più viste proprio come abbiamo<br />

visto nel capitolo 10. Salviamo tutte le classi che abbiamo appena modificato e apriamo il file<br />

“SampleTwitterClientViewController.xib”. Inseriamo un elemento “UIViewController”:<br />

Selezioniamo poi tale elemento e in “Identity Inspector” selezioniamo come classe “TabellaTwitterViewController”.<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 154


Nell’”Attributes Inspector” selezioniamo il file xib che deve essere associato a questa vista, ovvero<br />

“tabellaTwitterViewController”:<br />

Spostiamoci, infine, nel “File’s Owner” e colleghiamo l’elemento “tabellaTwitterViewController”<br />

con l’elemento UIViewController appena inserito. Ecco come deve presentarsi il pannello<br />

dopo il collegamento:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 155


Abbiamo concluso! Salviamo tutto, chiudiamo Interface Builder, clicchiamo su “Build and Go!”<br />

e testiamo il nostro <strong>per</strong>sonalissimo client di Twitter!<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 156


PARTE 3: IL SALVATAGGIO DEI DATI<br />

In questa terza e ultima parte vedremo come utilizzare la classe NSUserDefault, che ci <strong>per</strong>mette<br />

di salvare delle informazioni relative alla nostra applicazione. Quello che andremo a salvare<br />

sarà la data in cui è stato eseguito l’ultimo refresh della timeline, che mostreremo all’avvio<br />

all’utente.<br />

Ovviamente questa è una semplificazione, in applicazioni più complesse potremmo avere molte<br />

più informazioni da memorizzare (ad esempio dei settaggi come l’autorefresh, il nome utente o<br />

la password). Analizzeremo, quindi, solo il salvataggio di un parametro, ma vedrete che non sarà<br />

nulla di difficile!<br />

La prima cosa da fare è inserire una label in cui venga visualizzata l’ultima data in cui è stato<br />

eseguito un refresh della nostra timeline.<br />

Nel file “SampleTwitterClientViewController.h” inseriamo la seguente dichiarazione (righe 12 e<br />

24):<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

12<br />

13<br />

14<br />

15<br />

16<br />

17<br />

18<br />

19<br />

20<br />

21<br />

22<br />

23<br />

24<br />

25<br />

26<br />

#import <br />

#import "MGTwitterEngine.h"<br />

@class Tweet;<br />

@class TabellaTwitterViewController;<br />

@interface SampleTwitterClientViewController : UIViewController<br />

{<br />

! MGTwitterEngine *twitterEngine;<br />

! NSMutableArray *listaTweet;<br />

!<br />

! IBOutlet UIActivityIndicatorView *spinner;<br />

! IBOutlet UILabel *labelUltimoRefresh;<br />

!<br />

! TabellaTwitterViewController *tabellaTwitterViewController;<br />

}<br />

-(NSString*)getMessaggio:(NSDictionary*)element;<br />

-(NSString*)getUser:(NSDictionary*)element;<br />

-(NSURL*)getUrlImage:(NSDictionary*)element;<br />

@pro<strong>per</strong>ty (nonatomic, retain) NSMutableArray *listaTweet;<br />

@pro<strong>per</strong>ty (nonatomic, retain) IBOutlet UIActivityIndicatorView<br />

*spinner;<br />

@pro<strong>per</strong>ty (nonatomic, retain) IBOutlet TabellaTwitterViewController<br />

*tabellaTwitterViewController;<br />

@pro<strong>per</strong>ty (nonatomic, retain) IBOutlet UILabel *labelUltimoRefresh;<br />

@end<br />

Salviamo il file e apriamo poi “SampleTwitterClientViewController.xib”, che aprirà IB. Inserite<br />

una o due label (a vostro piacere), io ho fatto così:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 157


La seconda label (quella che contiene il testo “Label”) sarà quella che visualizzerà la data dell’ultimo<br />

refresh della timeline. Selezionate il “File’s Owner” e collegate l’elemento “labelUltimo-<br />

Refresh”, che abbiamo appena definito, con la label in questione. Se avete eseguito il collegamento<br />

in maniera corretta avrete il seguente risultato:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 158


Abbiamo così completato questo step. Possiamo salvare tutto e chiudere Interface Builder.<br />

GESTIAMO IL CARICAMENTO / SALVATAGGIO DEI DATI<br />

Ora possiamo occuparci del codice che ci interessa, che andrà inserito nel file<br />

“SimpleTwitterClientViewController.m”.<br />

Prima di fare qualsiasi cosa, ricordiamoci di importare la pro<strong>per</strong>ty definita in precedenza, tramite<br />

la seguente istruzione (dovete solo aggiungere “labelUltimoRefresh”, le altre le avete già<br />

definite):<br />

1 @synthesize listaTweet, spinner, tabellaTwitterViewController, labelUltimoRefresh;<br />

Possiamo passare alla parte più importante. Vediamo, quindi, come salvare i valori che ci interessano.<br />

Come abbiamo già detto, dobbiamo salvare la data dell’ultimo refresh che l’applicazione<br />

ha eseguito.<br />

Il punto migliore <strong>per</strong> eseguire il salvataggio è dopo la creazione della lista con i vari tweet, che<br />

avviene nel metodo “statusesReceived: forRequest:”. Ecco, quindi, il codice da inserire in tale<br />

metodo:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

[spinner stopAnimating];<br />

!<br />

NSDate *dataCorrente = [NSDate date];<br />

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];<br />

[defaults setObject:dataCorrente forKey:@"data"];<br />

[defaults synchronize];<br />

!<br />

[self presentModalViewController:self.tabellaTwitterViewController<br />

animated:YES];<br />

Nel istruzioni alle righe 1 e 8 le trovete già (le abbiamo inserite nei precedenti tutorial), dovete<br />

solo inserire le restanti. Alla riga 3 abbiamo istanziato un elemento di tipo NSDate, richiamando<br />

poi il metodo “date”, che ci restituisce la data e l’ora corrente. Abbiamo ottenuto, quindi, la<br />

data dell’ultimo refresh.<br />

Alla riga 4 e 5 eseguiamo il salvataggio vero e proprio: prima viene istanziato un oggetto di tipo<br />

NSUserDefault, poi si salvano al suo interno i valori desiderati. Ci sono vari metodi che devono<br />

essere utilizzati <strong>per</strong> salvare le variabili, a seconda del loro tipo. Nel nostro caso abbiamo utilizzato<br />

“setObject”, in quanto NSDate è un oggetto generico. Eccovi altri esempi di metodo <strong>per</strong> il<br />

salvataggio di variabili:<br />

1. [defaults setInteger:5 forKey:@"numeroIntero"];<br />

2. [defaults setBool:YES forKey:@"valoreBooleano"];<br />

3. [defaults setFloat:0.24 forKey:@"numeroFloat"];<br />

Come potete notare ci sono vari metodi, a seconda del tipo di variabile. Li trovate tutti, comunque,<br />

nella documentazione.<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 159


L’ultima istruzione è alla riga 6, ovvero la chiamata del metodo “synchronize”. Non fateci troppo<br />

caso, inseritela. Chi di voi svilup<strong>per</strong>à applicazioni con multithread o accesso a risorse condivise<br />

dovrà sviluppare questo aspetto, <strong>per</strong> gli altri non è nulla di importante.<br />

Ora non ci resta che inserire il codice che deve occuparsi della lettura del valore salvato. Tale<br />

lettura va eseguita, ovviamente, all’avvio dell’applicazione. Nel metodo “viewDidLoad”, quindi,<br />

aggiungiamo il codice seguente (dalla riga 14 alla 19):<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

12<br />

13<br />

14<br />

15<br />

16<br />

17<br />

18<br />

19<br />

20<br />

21<br />

22<br />

-(void)viewDidLoad{<br />

!<br />

! // Username e password <strong>per</strong> accedere a Twitter<br />

NSString *username = @"user_name";<br />

NSString *password = @"password";<br />

// Create a TwitterEngine and set our login details.<br />

twitterEngine = [[MGTwitterEngine alloc] initWithDelegate:self];<br />

[twitterEngine setUsername:username password:password];<br />

// <strong>Get</strong> updates from people the authenticated user follows.<br />

[twitterEngine getFollowedTimelineFor:username since:nil<br />

startingAtPage:0];<br />

!<br />

! NSDate *dataUltimoAgg = [[NSUserDefaults standardUserDefaults]<br />

objectForKey:@"data"];<br />

! if (dataUltimoAgg == nil) {<br />

! ! labelUltimoRefresh.text = @"nessun refresh precedente";<br />

! }else{<br />

! ! labelUltimoRefresh.text = [[NSString alloc]<br />

initWithFormat:@"%@",dataUltimoAgg];<br />

! }<br />

!<br />

! [spinner startAnimating];<br />

}<br />

Come potete vedere, abbiamo definito un oggetto di tipo NSDate, che dovrà contenere il valore<br />

della data che leggeremo dai salvataggi. Per leggere tale valore, utilizziamo un metodo appropriato,<br />

nel nostro caso è “objectForKey”. Se, invece, avessimo dovuto leggere un numero<br />

intero avremmo utilizzato il metodo “integerForKey”. Sono speculari, insomma, a quelli visti<br />

<strong>per</strong> il salvataggio dei dati. Nella documentazione, comunque, trovate tutti i metodi disponibili.<br />

Abbiamo poi eseguito un controllo su tale valore: nel caso l’oggetto sia nullo (quindi non è stato<br />

letto niente), vuol dire che l’applicazione è avviata <strong>per</strong> la prima volta, quindi scriviamo un<br />

testo appropriato. In caso contrario, inseriamo nella label la data letta.<br />

Abbiamo concluso anche il salvataggio dei dati!<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 160


Ecco il vostro client di Twitter completato e funzionante!!<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 161


Capitolo 16: Realizziamo il nostro “Brushes”<br />

Quello che ho pensato <strong>per</strong> voi questa volta è un po’ particolare, ma secondo me molto carino e<br />

con molte cose utili. Sicuramente tutti voi conoscerete Brushes (link iTunes), un programma<br />

molto famoso <strong>per</strong> disegnare sul proprio <strong>iPhone</strong> e iPod Touch.<br />

Ho pensato, quindi, di spiegarvi come realizzarne uno tutto vostro! Realizzeremo una vista che<br />

conterrà la “tavola grafica”, ovvero la parte in cui l’utente potrà diegnare. Ci sarà, poi, una seconda<br />

vista in cui inseriremo le impostazioni, <strong>per</strong> <strong>per</strong>mettere all’utente di cambiare il colore e<br />

la dimensione del pennello. Vedremo, infine, come fare in modo che l’utente possa salvare i<br />

propri disegni nell’Album foto dell’<strong>iPhone</strong>.<br />

PARTE 1: CREIAMO LA TAVOLA GRAFICA<br />

In questa prima parte vedremo come fare in modo che l’utente possa, muovendo il dito sullo<br />

schermo, disegnare a suo piacimento. Per questa applicazione sfrutteremo il template “Utility<br />

Application”, che ci <strong>per</strong>mette di avere già due viste, in modo da risparmiare un po’ di lavoro.<br />

CREIAMO UN NUOVO PROGETTO<br />

Iniziamo creando il progetto <strong>per</strong> la nostra applicazione. Create un nuovo progetto di tipo “Utility<br />

Application” e inserite “SampleBrushes” come nome.<br />

La struttura che abbiamo selezionato ci mette a disposizione due viste: una “Main View” che è<br />

quella che appare inizialmente, e una “Flipside View”, che appare se viene premuto il pulsante<br />

“i” (info), con un’animazione già definita. Queste due viste, quindi, potremo sfruttarle <strong>per</strong> creare<br />

la nostra applicazione: nella “Main View” creeremo la zona in cui l’utente potrà disegnare,<br />

mentre nella “Flipside View” inseriremo le impostazioni (quindi il colore del pennello, la dimensione,<br />

etc).<br />

Prima di definire l’aspetto grafico della nostra applicazione, definiamo un componente che poi<br />

andremo a collegare con un elemento in Interface Builder.<br />

Aprite, quindi, il file “MainViewController.h” (nella sottocartella “Main View”) e inserite le seguenti<br />

definizioni:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

#import "FlipsideViewController.h"<br />

@interface MainViewController : UIViewController <br />

{<br />

! IBOutlet UIImageView *viewDisegno;<br />

!<br />

}<br />

- (IBAction)showInfo;<br />

- (IBAction)cancella;<br />

@end<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 162


Alla riga 4 abbiamo definito un oggetto di tipo UIImageView, che sarà l’oggetto in cui l’utente<br />

disegnerà, e che visualizzerà, quindi, una serie di componenti grafiche colorate. Alla riga 9, invece,<br />

abbiamo definito un’azione, che ci servirà <strong>per</strong> cancellare tutto ciò che l’utente ha disegnato.<br />

DEFINIAMO L’ASPETTO GRAFICO DELL’APPLICAZIONE<br />

Salviamo il file e apriamo “MainView.xib”. Ci ritroveremo con una vista come questa:<br />

Dobbiamo modificarne un po’ l’aspetto. Iniziamo scegliendo come colore di sfondo il bianco<br />

(lo fate semplicemente dal pannello Attributes Inspector). Cancellate, inoltre, il bottone “i” che<br />

è presente nell’angolo basso destro della vista.<br />

Inserite, quindi, un componente di tipo “UIImageView”, in modo che occupi tutta la vista:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 163


Aggiungete, poi, una UIToolbar sul fondo della vista stessa. Io ho messo come stile della toolbar<br />

“Black Translucent”, ovviamente voi potete farla come preferite. Inserite, inoltre, due bottoni<br />

“Bar Button Item”, e un “Flexible Space Bar Button Item” tra i due. Il primo bottone rinominatelo<br />

in “Cancella” mentre il secondo in “Settings” (Impostazioni è troppo lunga come<br />

dicitura xD). Ecco l’aspetto finale della mia applicazione:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 164


Ovviamente sarebbe più carino inserire delle immagini nei bottoni, ma <strong>per</strong> semplicità ho inserito<br />

dei semplici nomi.<br />

Colleghiamo, ora, l’elemento e le azioni che abbiamo definito poco fa via codice (l’azione<br />

“showInfo” era già presente di default). Dal pannello dei documenti selezioniamo “File’s Owner”<br />

e spostiamoci in “Connections Inspector”. Colleghiamo “viewDisegno” con la UIImage-<br />

View che abbiamo inserito, l’azione “cancella” colleghiamola con l’omonimo pulsante, mentre<br />

“showInfo” collegatela con il bottone “Settings”. Se avrete eseguito tutto correttamente avrete<br />

un pannello delle connessioni come questo:<br />

Abbiamo concluso questa fase. Possiamo salvare il tutto e chiudere Interface Builder.<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 165


DEFINIAMO I METODI NECESSARI<br />

Torniamo ora al file “MainViewController.h”. Dobbiamo definire degli elementi che ci serviranno<br />

nel nostro programma. Ecco il codice da aggiungere a quello già presente:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

12<br />

13<br />

14<br />

15<br />

#import "FlipsideViewController.h"<br />

@interface MainViewController : UIViewController <br />

{<br />

! IBOutlet UIImageView *viewDisegno;<br />

!<br />

! CGPoint ultimoPunto;<br />

!<br />

! float dimensionePennello;<br />

! UIColor *colorePennello;<br />

}<br />

- (IBAction)showInfo;<br />

- (IBAction)cancella;<br />

@end<br />

Analizziamo gli elementi che abbiamo appena inserito. Alla riga 6 abbiamo definito un oggetto<br />

CGPoint, che non è altro che un contenitore delle due componenti di un punto: le coordinate<br />

x e y. Questo ci servirà <strong>per</strong> sa<strong>per</strong>e il punto precedente a quello considerato, <strong>per</strong>mettendoci così<br />

di tracciare una linea. Alla riga 8 e 9 definiamo le caratteristiche del pennello: dimensione e colore.<br />

La dimensione è una variabile di tipo reale (float), mentre il colore è definito dal tipo UI-<br />

Color, che inizializzeremo con lo standard RGB.<br />

Queste sono le uniche dichiarazioni di cui abbiamo bisogno. Salviamo quindi questo file e spostiamoci<br />

in “MainViewController.m”.<br />

Le azioni che ci interessa definire saranno da implementare in 3 metodi tipici della gestione del<br />

multitouch:<br />

1. touchesBegan, richiamato quando si inizia un movimento. Dovremo ricavare il punto in cui<br />

deve iniziare il disegno;<br />

2. touchesMoved, richiamato quando un movimento è in corso. Ogni volta che viene avviato<br />

deve disegnare un segmento colorato, in modo che appaia una linea raffigurante il disegno<br />

dell’utente;<br />

3. touchesEnded, metodo richiamato quando il movimento è terminato. In particolare serve<br />

quando l’utente compie solo un singolo tap, disegnando così un semplice punto.<br />

Iniziamo, quindi, a scrivere il codice necessario. Iniziamo con il metodo “viewDidLoad”:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 166


1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

- (void)viewDidLoad {<br />

[su<strong>per</strong> viewDidLoad];<br />

!<br />

! dimensionePennello = 5.0;<br />

! colorePennello = [[UIColor colorWithRed:1.0 green:0.0 blue:0.0<br />

alpha:1.0] retain];<br />

}<br />

Il suo compito è molto semplice e chiaro: viene impostata una dimensione standard del pennello,<br />

a 5.0 (pixel) e un colore, in questo caso il rosso. La definizione del colore avviene settando le<br />

componenti RGB, ovvero Red (rosso), Green (verde) e Blue (blu): variando le quantità con un<br />

valore compreso da 0.0 a 1.0 otterremo tutti i colori ammessi da questo sistema. Il campo alpha,<br />

invece, rappresenta la trasparenza. Fate qualche prova <strong>per</strong> prendere confidenza con questo<br />

sistema!<br />

Il secondo metodo che andiamo a definire è “touchesBegan”. La sua implementazione è molto<br />

semplice, dobbiamo solo ricavare il punto di inizio del movimento. Ecco il metodo da inserire:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {<br />

!<br />

! UITouch *touch = [touches anyObject];<br />

! ultimoPunto = [touch locationInView:viewDisegno];<br />

}<br />

Come vedete è molto semplice: dall’oggetto touch si ricava il punto (sempre definito come<br />

CGPoint), che viene assegnato all’oggetto “ultimoPunto” (riga 4). È importante specificare<br />

“viewDisegno” come parametro della funzione “locationInView”, altrimenti ricaverete tocchi<br />

relativi anche ad altre parti dello schermo, che <strong>per</strong>ò a noi non interessano.<br />

Passiamo ora alla definizione del metodo più impegnativo e importante: “touchesMoved”. Ecco<br />

il metodo da inserire:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 167


1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

12<br />

13<br />

14<br />

15<br />

16<br />

17<br />

18<br />

19<br />

20<br />

21<br />

22<br />

23<br />

24<br />

25<br />

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {<br />

! UITouch *touch = [touches anyObject];!<br />

! CGPoint puntoCorrente = [touch locationInView:viewDisegno];<br />

!<br />

! // definiamo il contest grafico<br />

! UIGraphicsBeginImageContext(viewDisegno.frame.size);<br />

! [viewDisegno.image drawInRect:CGRectMake(0, 0,<br />

viewDisegno.frame.size.width, viewDisegno.frame.size.height)];<br />

! // settiamo la forma e la dimensione del pennello<br />

! CGContextSetLineCap(UIGraphics<strong>Get</strong>CurrentContext(), kCGLineCapRound);<br />

! CGContextSetLineWidth(UIGraphics<strong>Get</strong>CurrentContext(), dimensione-<br />

Pennello);<br />

! // convertiamo il colore e impostiamolo come colore del pennello<br />

! const CGFloat *components = CGColor<strong>Get</strong>Components([colorePennello<br />

CGColor]);<br />

! CGContextSetRGBStrokeColor(UIGraphics<strong>Get</strong>CurrentContext(), components[0],<br />

components[1], components[2], components[3]);<br />

! // disegna il <strong>per</strong>corso<br />

! CGContextBeginPath(UIGraphics<strong>Get</strong>CurrentContext());<br />

! CGContextMoveToPoint(UIGraphics<strong>Get</strong>CurrentContext(),<br />

ultimoPunto.x, ultimoPunto.y);<br />

! CGContextAddLineToPoint(UIGraphics<strong>Get</strong>CurrentContext(),<br />

puntoCorrente.x, puntoCorrente.y);<br />

! CGContextStrokePath(UIGraphics<strong>Get</strong>CurrentContext());<br />

! // settiamo il disegno appena creato<br />

! viewDisegno.image = UIGraphics<strong>Get</strong>ImageFromCurrentImageContext();<br />

! UIGraphicsEndImageContext();<br />

!<br />

! ultimoPunto = puntoCorrente;!<br />

}<br />

Iniziamo ad analizzare passo passo il codice che abbiamo appena scritto.<br />

Alla riga 7 troviamo la definizione di un “Graphics Contexts”. Questo è un aspetto complesso<br />

del Core Graphics, ma utilizzando questa funzione lo adattiamo semplicemente alla nostra<br />

UIImageView, che infatti gli passiamo come parametro. Questo ci <strong>per</strong>metterà di disegnare all’interno<br />

della nostra immagine. Con l’istruzione seguente, infatti, definiamo l’area in cui potremo<br />

disegnare: essa avrà la stessa dimensione dell’immagine “viewDisegno”.<br />

Le righe 10 e 11 si riferiscono alla definizione del “pennello”, con cui l’utente disegnerà sullo<br />

schermo. Prima, infatti, viene impostata la forma (in questo caso “kCGLineCapRound” è di<br />

forma circolare, ma possiamo anche farlo quadrato o triangolare, vi basta guardare la documentazione<br />

<strong>per</strong> vedere gli altri valori possibili), poi la dimensione, passando ovviamente la variabile<br />

“dimensionePennello”, che contiene proprio il valore desiderato (riga 11).<br />

Le righe 13 e 14 servono <strong>per</strong> impostare il colore al nostro pennello. Abbiamo visto prima che il<br />

colore è definito da un elemento UIColor. Purtroppo dobbiamo convertire le varie componenti<br />

in CGFloat, e l’unico modo che ho trovato è quello che vedete nel codice. Prima convertiamo<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 168


l’elemento “colorePennello” in un array di tipo CGFloat (riga 13), poi passiamo le varie componenti<br />

all’istruzione che setta il colore del pennello (riga 14).<br />

Le righe dalla 16 alla 19 sono quelle che si occupano del disegno vero e proprio della linea. Partendo<br />

da “ultimoPunto” fino a “puntoCorrente” viene disegnato un tratto, un disegno, che<br />

comporrà poi il tratto voluto dall’utente.<br />

Le righe 21 e 22 settano il disegno che è stato creato nell’immagine “viewDisegno”, rendendola<br />

così visibile all’utente.<br />

Come vedete non è poi così complicato il codice, <strong>per</strong>ò bisogna fare attenzione a non dimenticare<br />

niente.<br />

Manca poco <strong>per</strong> terminare il nostro programma! Dobbiamo definire il metodo “touchesEnded”.<br />

Esso dovrà esattamente fare le stesse cose che fa il metodo “touchesMoved”. Potremmo<br />

anche non implementare questo metodo, <strong>per</strong>ò in caso di singolo tap non succederebbe niente,<br />

mentre noi vogliamo disegnare un singolo punto. Ovviamente potete <strong>per</strong>sonalizzare questo<br />

aspetto, decidendo voi l’azione da compiere. Ecco il codice da inserire se volete che ad un singolo<br />

tap venga disegnato un punto:<br />

1<br />

2<br />

3<br />

4<br />

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {<br />

!<br />

! [self touchesMoved:touches withEvent:event];<br />

}<br />

Come vedete non facciamo altro che richiamare il metodo “touchesMoved”, davvero semplicissimo.<br />

L’ultima cosa da fare è l’implementazione del metodo “cancella”. Anche questo è davvero molto<br />

semplice, <strong>per</strong> cancellare tutto ciò che l’utente ha disegnato basta porre a “nil” l’immagine:<br />

1<br />

2<br />

3<br />

- (IBAction)cancella{<br />

! viewDisegno.image = nil;<br />

}<br />

Davvero semplice!<br />

Abbiamo concluso questa prima parte del nostro tutorial! Clicchiamo “Build and Run” e testiamo<br />

il nostro <strong>per</strong>sonalissimo Brushes!<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 169


PARTE 2: INSERIAMO I SETTAGGI<br />

In questa seconda parte aggiungeremo alcuni aspetti fondamentali <strong>per</strong> migliorare l’applicazione:<br />

la possibilità di cambiare la dimensione e il colore del pennello, e la possibilità di salvare i<br />

disegni.<br />

Vedremo, quindi, come due classi diverse possano comunicare tra loro, e come utilizzare il metodo<br />

“imageSavedToPhotosAlbum” che <strong>per</strong>mette di salvare delle immagini nella galleria dell’utente.<br />

AGGIUNGIAMO LE IMPOSTAZIONI<br />

Iniziamo dichiarando nella classe “FlipsideViewController.h” gli elementi che poi andremo a<br />

definire in Interface Builder. Ecco il codice da inserire:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 170


1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

12<br />

13<br />

14<br />

15<br />

16<br />

17<br />

18<br />

19<br />

20<br />

21<br />

22<br />

23<br />

24<br />

25<br />

26<br />

27<br />

28<br />

@protocol FlipsideViewControllerDelegate;<br />

@interface FlipsideViewController : UIViewController {<br />

! id delegate;<br />

!<br />

! IBOutlet UISlider *sliderRosso, *sliderBlu, *sliderVerde, *sliderAlpha,<br />

*sliderDimensione;<br />

! IBOutlet UIImageView *viewColore;<br />

! IBOutlet UILabel *labelDimensione;<br />

!<br />

! UIColor *colorePennello;<br />

! float dimensionePennello;<br />

}<br />

@pro<strong>per</strong>ty (nonatomic, assign) id <br />

delegate;<br />

@pro<strong>per</strong>ty (nonatomic, assign) UIColor *colorePennello;<br />

@pro<strong>per</strong>ty (nonatomic, assign) float dimensionePennello;<br />

- (IBAction)done;<br />

- (IBAction)cambiaColore;<br />

- (IBAction)cambiaDimensione;<br />

@end<br />

@protocol FlipsideViewControllerDelegate<br />

- (void)flipsideViewControllerDidFinish:(FlipsideViewController<br />

*)controller nuovoColore:(UIColor*)colore<br />

nuovaDimensione:(float)dimensione;<br />

@end<br />

Parte di questo codice è già presente nella classe. Alle righe 7, 8, 9 abbiamo definito gli elementi<br />

grafici che ci serviranno. Come potete vedere, ci serviranno tre slider <strong>per</strong> cambiare il colore del<br />

pennello (più uno <strong>per</strong> la trasparenza, “alpha”), una UIImageView in cui mostreremo il colore<br />

corrente, in modo che l’utente possa vedere subito quale colore sta selezionando, uno slider e<br />

una label <strong>per</strong> la dimensione del pennello. Abbiamo, inoltre, definito due nuove azioni (righe 20<br />

e 21): esse verranno richiamate quando si muovono gli slider.<br />

Salviamo il file e apriamo “FlipsideView.xib”. Inserite i componenti necessari in modo da avere<br />

una struttura come la seguente:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 171


Dobbiamo eseguire i collegamenti con gli elementi che abbiamo definito in precedenza. Dal<br />

Pannello dei Documenti selezionate il “File’s Owner” e nel pannello “Connection Inspector”<br />

collegate i vari slider e la UIImageView (niente di difficile). Se avete eseguito questi collegamenti<br />

correttamente avrete un pannello come questo:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 172


Dobbiamo adesso collegare anche le due azioni. Collegate “cambiaColore” con tutti e quattro<br />

gli slider del colore, selezionando ogni volta “Value Changed” nel menù che vi appare. Collegate,<br />

infine, “cambiaDimensione” con lo slider della dimensione del pennello. Ecco come appare<br />

il vostro pannello con tutti i collegamenti effettuati:<br />

Abbiamo quasi concluso questa parte. Ci manca solo la definizione dei valori massimi e minimi<br />

dei vari slider. Selezioniamo il primo slider (quello <strong>per</strong> il rosso), spostiamoci nell’Attributes Inspector<br />

e controlliamo che come “Minumum Value” sia impostato 0.0, mentre come “Maximum<br />

Value” ci sia 1.0:<br />

Controllate anche i restanti slider dedicati al colore.<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 173


Per lo slider della dimensione, invece, dobbiamo impostare dei valori diversi. Io ho scelto 1.0<br />

come minimo, e 25.0 come massimo. Ovviamente potete variare come volete questi valori, magari<br />

effettuando delle prove.<br />

Abbiamo concluso la definizione grafica del pannello delle impostazioni. Salviamo il file e chiudiamo<br />

Interface Builder.<br />

SCRIVIAMO IL CODICE NECESSARIO<br />

Dobbiamo ora impostare il codice necessario. Apriamo il file “FlipsideViewController.m” e iniziamo<br />

ad inserire questo codice:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

12<br />

13<br />

14<br />

15<br />

16<br />

17<br />

18<br />

19<br />

#import "FlipsideViewController.h"<br />

@implementation FlipsideViewController<br />

@synthesize delegate, colorePennello, dimensionePennello;<br />

- (void)viewDidLoad {<br />

[su<strong>per</strong> viewDidLoad];<br />

self.view.backgroundColor = [UIColor viewFlipsideBackgroundColor];<br />

!<br />

! const CGFloat *components = CGColor<strong>Get</strong>Components([colorePennello<br />

CGColor]);<br />

! [sliderRosso setValue:components[0]];<br />

! [sliderVerde setValue:components[1]];<br />

! [sliderBlu setValue:components[2]];<br />

! [sliderAlpha setValue:components[3]];<br />

! [viewColore setBackgroundColor:colorePennello];<br />

! labelDimensione.text = [NSString<br />

stringWithFormat:@"%f",dimensionePennello];<br />

! [sliderDimensione setValue:dimensionePennello];<br />

}<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 174


Per prima cosa ricordatevi di inserire le @synthesize degli elementi “colorePennello” e “dimensionePennello”.<br />

Questi due valori li passeremo direttamente dalla “MainView”, quindi è importante<br />

che ci siano le due proprietà impostate correttamente. Passeremo i due valori in modo<br />

che all’a<strong>per</strong>tura del pannello <strong>per</strong> modificare il pennello l’utente trovi i valori correnti che sta<br />

utilizzando (quindi colore e dimensione attuali).<br />

Nel metodo “viewDidLoad” facciamo proprio quello che vi ho appena detto, ovvero inizializziamo<br />

i componenti grafici ai valori del pennello. All’avvio dell’applicazione tali valori saranno<br />

rosso <strong>per</strong> il colore, e 5.0 <strong>per</strong> la dimensione. Questi valori, <strong>per</strong>ò, potranno essere variati dall’utente,<br />

quindi è necessario che ogni volta che viene a<strong>per</strong>ta la vista delle impostazioni essi siano<br />

settati correttamente. In particolare, ricaviamo dal colore le varie componenti (come abbiamo<br />

già visto nella prima parte del tutorial), e settiamo il valore degli slider (righe 11-15). Alla<br />

riga 16 impostiamo il colore della UIImageView, che ci mostrerà così il colore del nostro pennello.<br />

Le ultime due righe, infine, servono <strong>per</strong> ricavare la dimensione del pennello e settare la<br />

label predisposta.<br />

Dobbiamo ora definire le due azioni collegate agli slider. Ecco i due metodi (davvero semplici)<br />

da implementare:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

- (IBAction)cambiaColore{<br />

! [viewColore setBackgroundColor:[UIColor<br />

colorWithRed:sliderRosso.value green:sliderVerde.value<br />

blue:sliderBlu.value alpha:sliderAlpha.value]];<br />

}<br />

- (IBAction)cambiaDimensione{<br />

! labelDimensione.text = [NSString<br />

stringWithFormat:@"%f",sliderDimensione.value];<br />

}<br />

Il primo metodo (“cambiaColore”) non fa altro che leggere i valori degli slider e settare lo sfondo<br />

dell’immagine con l’UIColor corrispondente. Il secondo metodo lavora nello stesso modo,<br />

solamente che visualizza il valore dello slider della dimensione del pennello. Semplici vero?<br />

Ci manca solo una modifica ad un metodo già esistente. Dobbiamo, infatti, passare alla classe<br />

“MainView” i nuovi valori della dimensione e del colore del pennello. Modifichiamo, quindi, il<br />

metodo “done” nel seguente modo:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

- (IBAction)done {<br />

! dimensionePennello = sliderDimensione.value;<br />

! colorePennello = [UIColor colorWithRed:sliderRosso.value<br />

green:sliderVerde.value blue:sliderBlu.value<br />

alpha:sliderAlpha.value];<br />

! [self.delegate flipsideViewControllerDidFinish:self<br />

nuovoColore:colorePennello nuovaDimensione:dimensionePennello];!<br />

}<br />

Abbiamo semplicemente letto il valore della dimensione e del colore del pennello, <strong>per</strong> poi passarlo<br />

al metodo “flipsideviewControllerDidFinish”, che abbiamo opportunamente modificato<br />

(infatti vedrete che ci sono dei nuovi parametri che gli vengono passati).<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 175


Torniamo al file “FlipsideViewController.h” e modifichiamo anche l’intestazione del metodo<br />

che troviamo nel fondo della classe:<br />

1<br />

2<br />

3<br />

@protocol FlipsideViewControllerDelegate<br />

- (void)flipsideViewControllerDidFinish:(FlipsideViewController<br />

*)controller nuovoColore:(UIColor*)colore<br />

nuovaDimensione:(float)dimensione;<br />

@end<br />

Abbiamo quasi terminato.<br />

Torniamo al file “MainViewController.m”, dobbiamo modificare due cose. Dobbiamo fare in<br />

modo che venga passato alla vista delle impostazioni i valori del pennello, e, viceversa, che vengano<br />

aggiornati dopo che l’utente li ha variati.<br />

Iniziate modificando il metodo “flipsideViewControllerDidFinish”, che trovate già nella vostra<br />

classe:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

- (void)flipsideViewControllerDidFinish:(FlipsideViewController<br />

*)controller nuovoColore:(UIColor*)colore<br />

nuovaDimensione:(float)dimensione{<br />

! const CGFloat *components = CGColor<strong>Get</strong>Components([colore CGColor]);<br />

! colorePennello = [[UIColor colorWithRed:components[0]<br />

green:components[1] blue:components[2] alpha:components[3]] retain];<br />

! dimensionePennello = dimensione;<br />

!<br />

! [self dismissModalViewControllerAnimated:YES];<br />

}<br />

Come potete vedere, è stata <strong>per</strong> prima cosa modificata l’intestazione del metodo (proprio quello<br />

che vi ho accennato poco fa). Vengono, poi, aggiornate le caratteristiche del pennello, inserendo<br />

il nuovo colore e la nuova dimensione.<br />

Il secondo metodo da modificare è “showInfo”, anch’esso già definito da XCode:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

12<br />

- (IBAction)showInfo {<br />

!<br />

! FlipsideViewController *controller = [[FlipsideViewController<br />

alloc] initWithNibName:@"FlipsideView" bundle:nil];<br />

! controller.delegate = self;<br />

! controller.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;<br />

!<br />

! controller.dimensionePennello = dimensionePennello;<br />

! controller.colorePennello = colorePennello;<br />

!<br />

! [self presentModalViewController:controller animated:YES];<br />

!<br />

! [controller release];<br />

}<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 176


A questo metodo aggiungiamo solo le righe 6 e 7, in modo da passare alla vista delle impostazioni<br />

le proprietà correnti del nostro pennello (quelle che vengono lette nel metodo<br />

“viewDidLoad” che abbiamo scritto prima).<br />

Abbiamo concluso anche questa parte.<br />

INSERIAMO IL SALVATAGGIO DEL DISEGNO<br />

Vogliamo ora aggiungere una funzione molto importante: il salvataggio del disegno creato. Vogliamo<br />

<strong>per</strong>mettere all’utente, quindi, di salvare il suo disegno, in modo che possa poi ritrovarlo<br />

nel Rullino Fotografico.<br />

Iniziamo definendo in “MainViewController” un metodo che assoceremo ad un pulsante nella<br />

nostra applicazione. Ecco cosa dovete aggiungere nel file “MainViewController.h”:<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

12<br />

13<br />

14<br />

15<br />

16<br />

#import "FlipsideViewController.h"<br />

@interface MainViewController : UIViewController <br />

{<br />

! IBOutlet UIImageView *viewDisegno;<br />

!<br />

! CGPoint ultimoPunto;<br />

!<br />

! float dimensionePennello;<br />

! UIColor *colorePennello;<br />

}<br />

- (IBAction)showInfo;<br />

- (IBAction)cancella;<br />

- (IBAction)salva;<br />

@end<br />

Come vedete abbiamo aggiunto solo la definizione del metodo “salva” alla riga 14.<br />

Salviamo il file e apriamo la vista “MainView.xib”. Nella toolbar inseriamo un bottone, dal “File’s<br />

Owner” colleghiamo l’azione salva a tale bottone. Se avrete eseguito tutto correttamente<br />

avrete i seguenti risultati:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 177


Salvate tutto e spostatevi nel file “MainViewController.m”.<br />

Dobbiamo ora definire il metodo salva, scrivendo il codice necessario <strong>per</strong> salvare l’immagine<br />

nella galleria dell’utente. Ecco il codice da inserire:<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 178


1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

9<br />

10<br />

11<br />

12<br />

13<br />

14<br />

15<br />

16<br />

17<br />

18<br />

- (IBAction) salva{<br />

! UIImageWriteToSavedPhotosAlbum(viewDisegno.image, self, @selector(imageSavedToPhotosAlbum:<br />

didFinishSavingWithError: contextInfo:),<br />

nil);<br />

}<br />

- (void)imageSavedToPhotosAlbum:(UIImage *)image<br />

didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo<br />

{<br />

NSString *messaggio;<br />

NSString *titolo;<br />

if (!error) {<br />

! ! titolo = @"Salvataggio";<br />

messaggio = @"Immagine salvata con successo";<br />

! } else {<br />

titolo = @"Errore";<br />

! ! messaggio = [error description];<br />

! }<br />

! UIAlertView *alert = [[UIAlertView alloc] initWithTitle:titolo<br />

message:messaggio delegate:nil cancelButtonTitle:@"OK"<br />

otherButtonTitles:nil];<br />

! [alert show];<br />

! [alert release];<br />

}<br />

Come potete vedere il codice è molto semplice. Il metodo salva non fa altro che richiamare un<br />

metodo “imageSavedToPhotosAlbum”, che si occupa di salvare l’immagine nella galleria. In tale<br />

metodo, infatti, non vedrete istruzioni che si occupano del salvataggio, ma solo un controllo se<br />

l’o<strong>per</strong>azione è andata a buon fine. Viene infatti controllata la variabile “error” (riga 8), e viene<br />

impostato un messaggio da visualizzare poi all’utente, che dovrà essere avvisato se il salvataggio<br />

si è concluso correttamente oppure se ci sono stati degli errori.<br />

Tutto molto semplice come sempre!<br />

Abbiamo concluso! Cliccate su “Build and Go!” e testate il vostro programma funzionante!<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 179


<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 180


Bibliografia<br />

I miei tutorial spesso sono nati prendendo spunto da altre guide trovate su Internet, scritte da<br />

altre <strong>per</strong>sone. Mi pare corretto, quindi, riportare di seguito i link da cui ho preso alcuni tutorial,<br />

in modo da dare il giusto riconoscimento ai legittimi autori.<br />

Capitolo 3: <strong>iPhone</strong> <strong>SDK</strong> Articles, “First <strong>iPhone</strong> Application”,<br />

http://www.iphonesdkarticles.com/2008/07/first-iphone-application.html<br />

Capitolo 4: <strong>iPhone</strong> Development Central, “Trash<strong>Tutorial</strong>”,<br />

http://www.iphonedevcentral.org/tutorials.php?page=View<strong>Tutorial</strong>&id=30&uid=68863015<br />

Capitolo 5: <strong>iPhone</strong> Development Central, “UIToolbar and AutoRotation”,<br />

http://www.iphonedevcentral.org/tutorials.php?page=View<strong>Tutorial</strong>&id=48&uid=79444464<br />

Capitolo 6: <strong>iPhone</strong> Development Central, “UIProgressView <strong>Tutorial</strong>”,<br />

http://www.iphonedevcentral.org/tutorials.php?page=View<strong>Tutorial</strong>&id=43&uid=34167348<br />

Capitolo 7: <strong>iPhone</strong> Noob, “Access the Address Book”,<br />

http://iphone.zcentric.com/2008/09/19/access-the-address-book/<br />

Capitolo 11: iPod Touch Fans Forum, “[<strong>Tutorial</strong>] <strong>Get</strong>ting to know Xcode/Interface Buider: PARTS<br />

I & II: UITabBar projects”,<br />

http://www.ipodtouchfans.com/forums/showthread.php?t=137183<br />

Capitolo 14: The Apple <strong>Blog</strong>, “<strong>iPhone</strong> <strong>SDK</strong> <strong>Tutorial</strong>: Build a Simple RSS reader for the <strong>iPhone</strong>”,<br />

http://theappleblog.com/2008/08/04/tutorial-build-a-simple-rss-reader-for-iphone/<br />

Capitolo 16: iPod Touch Fans Forum, “[<strong>Tutorial</strong>] Drawing to the screen”,<br />

http://www.ipodtouchfans.com/forums/showthread.php?t=132024<br />

<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>! 181


Andrea Busi<br />

“<strong>Tutorial</strong> <strong>pratici</strong> <strong>per</strong> <strong>iPhone</strong> <strong>SDK</strong>”<br />

versione 1.6, dicembre 2010<br />

! 182

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!