Sei pronto a completare il primo progetto del corso che ti aiuta a creare app iOS con Swift? Nella prime due lezioni del Progetto 1, che ti ricordo ha lo scopo di realizzare un’app che mostra una lista di immagini, hai preso confidenza con Xcode e con la Storyboard, lo strumento messo a disposizione da Apple per realizzare interfacce grafiche. Inoltre hai iniziato a prendere dimestichezza con Swift ed alcuni concetti della programmazione ad oggetti.

Se ancora non hai memorizzato quanto fatto in precedenza non preoccuparti. L’importante è che tu riesca a capire quello che si sta facendo. La memoria verrà con il tempo, quando metterai in pratica con costanza le cose che stai imparando. Sei pronto a completare la tua prima applicazione?

In questa terza ed ultima parte del Progetto 1 ti mostrerò come aprire l’immagine a tutto schermo dopo aver selezionato una cella della tabella. Ti ricordo che puoi trovare l’elenco completo di tutte le lezioni nella pagina di introduzione del corso.

Progetto 1: Image Viewer

Realizzare una schermata di dettaglio della foto

A questo punto dell’applicazione siamo in grado di visualizzare una lista di immagini, cliccare su ognuna di esse ma nulla succede dopo il tocco. L’obiettivo di quest’ultima parte del primo progetto è quella di mostrare una schermata di dettaglio della foto che verrà aperta quando l’utente clicca su una cella. Vediamo come fare.

Questo compito può essere diviso in due sotto operazioni. La prima richiede la scrittura del codice necessario per mostrare la foto. La seconda operazione, invece, richiede la creazione dell’interfaccia grafica tramite Interface Builder.

Iniziamo con il compito più semplice. Scriviamo la parte di codice necessaria all’apertura della foto dopo aver selezionato la cella della tabella. Dalla barra dei menù seleziona File -> New -> File. Ti verrà mostrata una nuova finestra nella quale devi selezionare Cocoa Touch Class e poi cliccare su Next. 

Creare App iOS con Swift – Progetto 1 Parte 3

A questo punto ti verrà chiesto un nome da dare alla nuova schermata che stai creando ed anche che tipo di schermata dovrà essere. Inserisci DetailViewController nel campo ClassUIViewController nel campo Subclass of. Assicurati anche che Also create XIB file sia deselezionato e clicca du Next Create per creare la nuova schermata di dettaglio delle foto.

Creare App iOS con Swift – Progetto 1 Parte 3 - 1

Bene! Hai appena creato un nuovo file che conterrà tutto il codice per gestire la visualizzazione della foto a schermo intero. Hai visto quanto è semplice creare un nuovo file per gestire una nuova schermata? Nel campo Subclass of abbiamo inserito UIViewController perché abbiamo bisogno di una schermata vuota nella quale inserire una immagine. Se avessimo avuto bisogno di una schermata che contiene una tabella (come nel caso della tabella che contiene l’elenco delle immagini), avremmo potuto inserire UITableViewController.

La seconda operazione da fare richiede più tempo per essere portata a termine. Apri il file Main.storyboard. Vedrai i due view controller che hai creato in precedenza: il primo sulla sinistra è il navigation view controller (che si occupa di gestire la barra di navigazione superiore). il secondo invece è il table view controller (che si occupa di mostrare la lista delle immagini). Ora dobbiamo aggiungere un terzo view controller (quindi una nuova schermata) da collegare al file creato in precedenza e che si occuperà di mostrare a tutto schermo la foto selezionata.

Per inserire un nuovo view controller nella storyboard dobbiamo usare la libreria degli oggetti posta in basso a destra. Ricordi come si fa? Nelle precedenti lezioni ti ho mostrato come inserire un nuovo componente. Nella libreria degli oggetti cerca View Controller. Selezionalo e trascinalo nella schermata centrale, alla destra del table view controller. Il risultato dovrà essere simile a quanto mostrato in questa immagine.

Creare App iOS con Swift – Progetto 1 Parte 3 - 2

Se ora dai un’occhiata al document outline (che ti ricordo trovarsi sulla sinistra rispetto alla schermata centrale), una seconda voce chiamata View Controller scene è comparsa. Una è relativa alla tabella. La seconda, invece, alla schermata che abbiamo appena inserito.

Ricordi che quando abbiamo abbiamo creato la nostra table view cell nella precedente lezione le abbiamo dato un identificativo così da potervi accedere facilmente nel codice? Adesso dobbiamo fare una cosa simile con la nuova schermata. Seleziona il nuovo view controller. In document outline verrà evidenziato il componente chiamato View. Sopra di esso è presente la voce View Controller, affiancata da una icona gialla. Clicca su questa voce per selezionare l’intero view controller.

Creare App iOS con Swift – Progetto 1 Parte 3 - 3

A questo punto possiamo facilmente assegnare un nome al view controller. Spostati nella barra laterale destra ed accedi all’Identity Inspector. Puoi aprire questo menù selezionando la terza voce oppure con la combinazione di tasti cmdalt3.

Creare App iOS con Swift – Progetto 1 Parte 3 - 4

Trovato? Bene. Inserisci la parola Detail nel campo Storyboard ID. Questo sarà l’identificativo della schermata. Ora che ti trovi qui, nel campo Class inserisci DetailViewController. Ricordi a cosa serve questa operazione? In pratica stiamo collegando la schermata creata nella Storyboard con il file che abbiamo generato all’inizio di questa lezione.

Ora inizia la parte interessante. Dobbiamo infatti costruire la nostra schermata per visualizzare una immagine. Il componente che si occupa di mostrare immagini di chiama UIImageView. Come puoi intuire dal nome, questo componente fa parte della libreria UIKit (da qui il prefisso UI).

Ritorna alla libreria degli oggetti e questa volta ricerca Image View. Seleziona il componente e trascinalo all’interno del detail view controller. Ora clicca sui bordi e ridimensiona il componente affinché si adatti alle dimensioni della schermata.

Creare App iOS con Swift – Progetto 1 Parte 3 - 5

Non avendo inserito nessuna immagine, il componente UIImageView presenta uno sfondo azzurrino con una scritta al centro. In questo momento non andremo ad assegnare nessun contenuto a questo oggetto. Lo faremo via codice caricando dinamicamente l’immagine selezionata nella tabella. Non spaventarti, non è nulla di troppo complesso. Ti mostrerò come fare passo dopo passo!

Ma prima di passare al caricamento delle immagini, devi sapere che c’è un piccolo problema con la schermata che abbiamo appena creato. L’immagine non occuperà sempre tutta la dimensione dello schermo del dispositivo che sta eseguendo l’applicazione. Questa affermazione può sembrare un po’ strana. In fondo abbiamo ridimensionato il componente UIImageView affinché occupasse tutta la dimensione del display. Segui il mio ragionamento. esistono diversi dispositivi iOS con dimensioni dello schermo differenti. Come dovrebbe comportarti la nostra applicazione quando viene eseguita su un iPhone X oppure su un iPad?

iOS ha una risposta semplice a questo quesito. La soluzione si chiama Auto Layout. Esso permette di definire delle regole su come la tua schermata deve comportarsi ed automaticamente tutti i componenti si adattano alle dimensioni dello schermo del dispositivo che sta eseguendo l’app. Le regole che è necessario definire devono però essere esaustive:

  • Bisogna definire delle regole per posizionare nello spazio senza ambiguità un componente;
  • Le regole non devono andare in conflitto tra di loro.

È possibile creare le regole per Auto Layout, conosciute come constraints, direttamente da Interface Builder, che ci segnalerà gli eventuali problemi presenti con le regole inserite.

Nel nostro caso specifico avremo bisogno di quattro semplici regole. Noi vogliamo che l’immagine occupi l’intero schermo del dispositivo, perciò dobbiamo definire una regola per la parte superiore dell’immagine una per la parte inferiore, una per la parte sinistra ed infine una per la parte destra. Esistono diversi metodi per aggiungere le regole. Il metodo più semplice (che funziona molto bene in casi semplici come questo) è quello di selezionare la UIImageView e poi cliccare nella barra dei menù la voce Editor -> Resolve Auto Layout Issues -> Reset To Suggested Constraints.

Visivamente il layout dell’applicazione non sarà cambiato. Ma sono presenti due piccole differenze. La prima è che è presente una leggera linea sottile intorno all’image view. Questo è il modo di Interface Builder di segnalare che le regole sono state inserite correttamente.

Il secondo cambiamento è in document outline. Una nuova voce chiamata Contraints si è posizionata sotto Image View. Se espandi questa voce puoi vedere tutte le quattro regole che sono state inserite. Parleremo in un’altra lezione delle regole di Auto Layout. Nel frattempo puoi iniziare a curiosare vedendo le regole che Xcode ha auto generato.

Creare App iOS con Swift – Progetto 1 Parte 3 - 6

Dopo aver finito di aggiungere le regole, ci rimane da fare un’ultima cosa prima di chiudere Interface Builder: collegare l’immagine con il codice. Come puoi facilmente intuire, avere inserito l’oggetto UIImageView all’interno della nostra interfaccia non è sufficiente. Dobbiamo avere un riferimento dell’image view nel file contenente il codice della schermata di dettaglio al fine di poter caricare l’immagine che vogliamo mostrare.

Per questo motivo dobbiamo creare una proprietà della image view nel codice, che dovremo collegare con l’interfaccia grafica. Questa proprietà è simile all’array var immagini che abbiamo creato nelle precedenti lezioni nel file ViewController.swift. La proprietà che vogliamo creare ora, però, ha delle differenze che vorrei spiegarti. Ma facciamo un passo alla volta.

Xcode è uno strumento molto potente e ci mette a disposizione tutto quello di cui abbiamo bisogno per facilitarci lo sviluppo di applicazioni. Una funzionalità che ci torna utile in questo momento si chiama Assistant Editor, che divide in due l’interfaccia di Xcode: da un lato continua a mostrare la schermata visualizzata prima di attivare Assistant Editor, nell’altro mostra una schermata che in qualche modo può essere collegata alla prima. Nel nostro caso, se avviamo Assistant Editor mentre stiamo visualizzando Interface Builder con il DetailViewController selezionato, nella seconda schermata verrà mostrato il file contenente il codice che abbiamo collegato alla nostra schermata (quindi il file DetailViewController.swift). Quanto scritto è più facile a farsi che a dirsi, quindi procediamo!

Recati nel file Main.storyboard ed assicurati di selezionare il DetailViewController. A questo punto avvia Assistant Editor selezionando dalla barra dei menù la voce View -> Assistant Editor -> Show Assistant Editor. Puoi richiamare questa funzione anche con la combinazione di tasti alt + cmd + invio.

Creare App iOS con Swift – Progetto 1 Parte 3 - 7

Xcode dividerà la schermata in due, mostrando sulla sinistra Interface Builder e sulla destra il codice collegato alla schermata. L’editor conosce quale file è collegato alla schermata perché in precedenza abbiamo indicato che DetailViewController è la classe collegata alla nostra schermata. Ricordi?

A questo punto possiamo collegare l’elemento image view con il codice. Segui attentamente questi passi:

  • Nella finestra di sinistra seleziona il componente UIImageView.
  • Tieni premuto il tasto ctrl della tastiera.
  • Con il mouse clicca sull’image view continuando a premere il tasto ctrl e trascina il mouse verso destra, fino ad arrivare alla finestra contenente il codice.
  • Muovendo il mouse, noterai una linea blu che parte dall’image view. Trascina il mouse fino a portarlo tra la voce class Detail ViewController: UIViewController {override func viewDidLoad() {.

Creare App iOS con Swift – Progetto 1 Parte 3 - 7

  • Quando vedi comparire un box con scritto Insert Outlet or Outlet Collection, rilascia sia il tasto ctrl che il mouse.

Se hai seguito correttamente tutti i passaggi precedenti, un popup dovrebbe comparire con cinque voci: ConnectionObjectNameType e Storage.

Creare App iOS con Swift – Progetto 1 Parte 3 - 8

Lascia tutti i campi con la loro impostazione predefinita eccetto per il campo Name. Qui bisogna inserire il nome che vogliamo dare alla proprietà. Puoi inserire ad esempio imageView. Quando sei pronto, puoi cliccare su Connect e Xcode inserirà una nuova linea di codice in DetailViewController.swift.

Creare App iOS con Swift – Progetto 1 Parte 3 - 9

Partiamo dalla sinistra della nuova riga di codice che è stata inserita. La prima cosa che puoi notare è il cerchio riempito di grigio. Se passi il mouse su questo cerchio, puoi vedere come l’image view sulla sinistra si illumina. Questo sta ad indicare che la proprietà appena inserita è collegata con un elemento dell’interfaccia grafica.

Alcune parti di questa riga ti dovrebbero essere familiari. Altre, invece, sono completamente nuove.

  • @IBOutlet sta ad indicare che esiste una connessione tra il codice ed Interface Builder.
  • var dichiara una nuova variabile (o proprietà).
  • imageView è il nome assegnato alla variabile. Hai notato come il nome della variabile abbia la prima lettera minuscola? Questa è una convenzione. Tutte le proprietà o variabili hanno la prima lettera minuscola ed ogni altra parola contenuta nel nome inizia con la lettera maiuscola. Questa convenzione si chiama camel case.
  • UIImageView! dichiara che la proprietà è di tipo UIImageView. La proprietà potrebbe non esistere (quindi è opzionale) ma siamo certi che quando ci servirà essa esisterà, perciò viene inserito il punto esclamativo (!).

Vuoi sapere perché questa proprietà è opzionale? In breve, quando il Detail View Controller viene generato, la UIImageView non esiste. Pertanto la proprietà imageView è nil. Quando la schermata viene completamente caricata, ad imageView viene assegnato l’oggetto UIImageView, così che possiamo iniziare ad usarlo. Se ancora non hai ben chiaro il funzionamento degli opzionali non preoccuparti. Avrai modo e tempo per capirlo nelle prossime lezioni.

Bene! Ora l’interfaccia grafica è completamente collegata con il codice. Puoi chiudere Assistant Editor selezionando la voce di menù View -> Standard Editor -> Show Standard Editor. In questo modo avrai a disposizione tutta la finestra per scrivere codice. Pronto a collegare le immagini alla nostra schermata? Siamo quasi alla fine, tieni duro!

Caricare immagini con UIImage

Facciamo un riepilogo di quanto abbiamo ottenuto fino a questo momento. La prima schermata dell’app è una tabella (UITableViewController) che mostra la lista delle immagini che abbiamo caricato. Cliccando su una delle celle della tabella al momento non succede nulla. Però abbiamo già preparato la schermata che mostrerà l’immagine a tutto schermo (DetailViewController). Il prossimo obiettivo è quello di mostrare l’immagine a tutto schermo quando si seleziona una cella della tabella. Quindi, dal punto di vista tecnico, collegare la UITableViewController con la DetailViewController.

Per fare questo, dobbiamo utilizzare un altro metodo speciale nel ViewController. Questo metodo si chiama tableView(_, didSelectRowAt:), che mette a disposizione un IndexPath, proprio come nel metodo cellForRowAt che abbiamo visto nelle precedenti lezioni, che di dice quale cella della nostra tabella è stata selezionata. Quindi, ogni volta che selezioniamo una cella, viene in automatico chiamato questo metodo che ci informa del numero della cella cliccata dall’utente. In questo metodo dobbiamo eseguire due operazioni:

  1. Dobbiamo creare (il termine corretto è instanziare) un nuovo oggetto di tipo DetailViewController.
  2. Passare al DetailViewController il nome dell’immagine che è stata selezionata. In questo modo il detail view controller può caricare l’immagine e mostrarla a tutto schermo nell’image view.

Per passare il nome dell’immagine al detail view controller è necessario creare una proprietà che possa contenere questa informazioni. Questa proprietà sarà di tipo String, ma deve essere opzionale perché il detail view controller, appena viene creato, non avrà questa informazioni. Infatti questa informazioni gliela passeremo noi dopo che l’oggetto DetailViewController è stato creato.

Come prima cosa dobbiamo creare la proprietà che conterrà il nome dell’immagine selezionata. Apri il DetailViewController e subito sotto la proprietà @IBOutlet weak var imageView: UIImageView! inserisci var immagineSelezionata: String?.

Creare App iOS con Swift – Progetto 1 Parte 3 - 10

Bene! La prima operazione è stata completata. Passiamo al compito successivo. Dobbiamo implementare il metodo didSelectRowAt nel file ViewController in modo che al tocco di una cella venga mostrata l’immagine in DetailViewController.

Se ricordi bene, quando abbiamo creato il detail view controller, abbiamo assegnato un nome allo Storyboard ID (nello specifico, il nome assegnato è Detail). Questo nome ci permette di caricare la schermata dalla storyboard più facilmente, usando il metodo instantiateViewController(withIdentifier:). Ogni view controller ha una proprietà chiamata storyboard che è o la storyboard che contiene il view controller oppure nil. Nel caso di ViewController, il valore di questa proprietà è Main.storyboard, che è anche lo stesso valore assegnato a detail view controller. Questa spiegazione è necessaria per capire cosa faremo nei prossimi passaggi. Nello specifico:

  • Caricheremo il detail view controller dalla nostra storyboard.
  • Assegneremo alla proprietà immagineSelezionata il nome corretto dell’immaine che è stata selezionata dall’utente.
  • Mostreremo il nuovo detail view controller.

Il primo di questi passaggi può essere eseguito chiamando il metodo instantiateViewController, ma questo metodo nasconde due piccole complessità. La prima è collegata alla proprietà storyboard, che come detto in precedenza è collegata ad ogni View Controller. Questa proprietà può essere nil perché esistono View Controller che non appartengono a nessuna storyboard. Per questo motivo dovremo gestire il valore opzionale che riceveremo.

La seconda complessità è che il metodo instantiateViewController() ci restituisce un oggetto di tipo UIViewController, anche se il view controller che abbiamo instanziato è di tipo DetailViewController. Questo avviene perché Swift non conosce qual è il tipo effettivo del view controller, perciò ci restituisce il tipo generico. Per questo motivo dovremo andare a dire a Swift qual è il tipo effettivo del View Controller (che nel nostro caso è DetailViewController).

Quello che ho appena descritto potrebbe leggermente confonderti, soprattutto se sei alle prime armi con la programmazione. Come ripeto spesso, non preoccuparti. Con il tempo e tanta pratica queste cose diventeranno più familiari.

Il termine tecnico della mia affermazione “dovremo andare a dire a Swift qual è il tipo effettivo del View Controller” è typecasting, cioè chiedere a Swift di trattare un valore come se fosse un tipo differente. In Swift questa operazione può essere svolta in modi differenti. Io ti mostrerò il metodo più sicuro: “per favore, cerca di trattare questa schermata come se fosse un DetailViewController. Se questo non è il tipo corretto, allora non fare niente e prosegui nell’esecuzione”.

Dopo che abbiamo ottenuto un DetailViewController, possiamo assegnare alla proprietà immagineSelezionata il nome dell’immagine prelevandola dall’array (immagini[indexPath.row]) così come abbiamo fatto nel metodo cellForRowAt. Questo passaggio è molto semplice.

L’ultimo passaggio è quello di mostrare il detail view controller. Ti ho già spiegato in precedenza come ogni UIViewController abbia una proprietà chiamata storyboard, che può contenere la storyboard a cui appartiene oppure può essere nil. Un’altra proprietà di UIViewController è navigationController. Anch’essa è opzionale e può contenere il navigation controller che contiene il view contrioller, se esiste, oppure è nil.

Questo è perfetto per l’obiettivo che vogliamo raggiungere, perché il navigation controller è responsabile di mostrare nuove schermate. Certamente il navigation controller si occupa di mostrare la barra grigia in alto allo schermo ma è anche responsabile di tenere una coda di tutte le finestre che l’utente ha navigato.

Di default, il navigation controller contiene il primo view controllar che è stato creato nella storyboard. Quando un nuovo view controller viene creato, è possibile inserirlo nella coda del navigation controller. Quando l’utente clicca sul tasto Indietro, il navigation controller in automatico distrugge il view controller che è visibile sullo schermo e recupera il primo view controller della coda per mostrarlo nuovamente.

Questi tre mini passaggi completano il metodo didSelectRowAt del ViewController.

Creare App iOS con Swift – Progetto 1 Parte 3 - 11

Diamo un’occhiata più da vicino a quanto appena scritto. Ci sono tre parti del codice che potrebbero fallire. Per questo motivo è necessario effettuare dei controlli per evitare che l’app vada in crash. La proprietà storyboard potrebbe essere nil, il metodo instantiateViewController() potrebbe fallire se passiamo un identificativo sbagliato (che non è stato assegnato a nessun view controller) ed il typecast (la parte contraddistinta da as?) potrebbe anch’esso fallire, perché potremmo ad esempio aver creato un view controller di un tipo diverso da DetailViewController.

Perciò ben tre cose potrebbero fallire in un’unica riga. Ma se hai seguito attentamente le mie indicazioni, non dovresti correre rischi. Questi potenziali problemi sono posti dopo le parole chiavi if  let. Il loro significato è molto semplice. Se almeno una di queste cose è nil, allora quanto scritto tra le parentesi graffe non viene eseguito. Altrimenti il codice tra parentesi graffe può essere eseguito senza alcun rischio.

È rimasta un’altra piccola cosa da fare prima di vedere in funzione quanto fatto. Dobbiamo caricare l’immagine dentro la UIImageView. In questa fase ti mostrerò un nuovo tipo di dato, chiamato UIImage. Questo tipo non ha View nel nome come UIImageView, perciò non ha nulla a che fare con le view. UIImage è un tipo di dato che viene usato per caricare dati di tipo immagine, come i PNG oppure i JPEG.

Quando si crea un oggetto di tipo UIImage, bisogna passare un parametro chiamato named, che rappresenta il nome dell’immagine che deve essere caricata. UIImage si occuperà di cercare il file collegato al nome che è stato passato all’interno del Bundle dell’app ed infine lo caricherà.

Ma ora passiamo alla pratica. April il file DetailViewController. Se ricordi bene, la proprietà immagineSelezionata è opzionale. Per questo motivo prima di caricare l’immagine dobbiamo verificare che la proprietà contenga realmente il nome del file. Aggiungi questo pezzo di codice subito dopo super.viewDidLoad().

Creare App iOS con Swift – Progetto 1 Parte 3 - 12

La prima nuova riga di codice controlla che il nome del file esista. Successivamente viene caricata l’immagine ed assegnata alla proprietà imageView.

Bene, siamo pronti! Puoi avviare l’applicazione. Ora dovresti essere in grado di selezionare una cella e vedere l’immagine corrispondente a tutto schermo. Hai fatto caso che se premi il bottone Back ritorni nuovamente alla lista delle immagini? Tutta questa parte viene gestita in automatica dalla libreria di Apple.

Provando l’applicazione avrai certamente notato una cosa: Le immagini sono distorte affinché riempiano l’intero schermo. È un risultato non piacevole da vedere. Vorrei sistemare questo piccolo aspetto prima di concludere il primo progetto. Apri il Main.storyboard e se lesiona l’oggetto UIImageView del DetailViewController.

Creare App iOS con Swift – Progetto 1 Parte 3 - 13

Ora sulla barra destra apri Attribute Inspector (la quarta voce di menù). Alla voce Content Mode seleziona Aspect Fit dal menù a tendina. A questo punto puoi riavviare l’app. Le immagini non saranno più distorte!

Creare App iOS con Swift – Progetto 1 Parte 3 - 14

Conclusioni

Complimenti, sei arrivato in fondo al primo progetto. So benissimo che non è stata semplice e che molti concetti ancora non sono molto chiari. Ma tieni duro, basta un po’ di pratica e tutto diventerà più semplice, te lo posso garantire.

Ricapitolando quanto fatto in queste tre lezioni, abbiamo visto cosa sono le costanti, le variabili, cosa significa fare override di un metodo, abbiamo imparato a gestire le table view e le immagini. Inoltre abbiamo lavorato con la storyboard ed Interface Builder. Non sono mancati gli opzionali, gli array, le UIImage e molto altro.

Di carne al fuoco ce n’è molta e sono sicuro che avrai già dimenticato tutto. Ma è tutto OK, perché tutti noi impariamo ripetendo le cose. E se continui a seguire le restanti lezioni, presto anche tu riuscirai a sviluppare app in autonomia. Ti aspetto alla prossima lezione! Ti ricordo che puoi trovare la repository di GitHub a questo link con tutto il codice delle lezioni.

Condividi.

Informazioni autore

Ingegnere Informatico laureato presso il Politecnico di Milano. Appassionato di tecnologia e programmazione. Esperto e utilizzatore dei prodotti Apple ma anche di Android e Linux.

Lascia un commento