DevTutorial #12 – Gestire più viste create con Interface Builder

Eccoci con un nuovo tutorial nei DevTutorial, dedicato alla programmazione con l’SDK per iPhone. Questa volta (su richiesta di parecchi utenti) ho deciso di trattare un argomento abbastanza ostico in XCode, ovvero la gestione di più viste create con Interface Builder. IB è uno strumento davvero ottimo che ci permette di creare la parte grafica della nostra applicazione senza grossi sforzi, ma spesso poi diventa problematico gestire tutte le vise via codice. In questo tutorial vedremo come creare due viste distinte, e come passare da una all’altra mediante un semplice bottone.

Vedrete che il tutto si rivelerà molto semplice e veloce (a differenza dei precedenti metodi che vi avevo esposto!).

1. Creiamo un nuovo progetto

Iniziamo il nostro tutorial creando un nuovo progetto di tipo “View-based application” e chiamiamolo “viewTutorial”.

Il tutorial ci mette già a disposizione una vista, che sarà quella di partenza (quella che viene caricata all’avvio dell’applicazione). Creiamo, per prima cosa, la seconda vista necessaria per questo tutorial. Facciamo clic con il tasto destro sul nome del nostro progetto e selezioniamo “Add -> New File…”. Scegliamo, poi, un template “UIViewController” e spuntiamo la voce “With XIB for user interface”:

Inseriamo come nome “VistaDue” e clicchiamo su “Finish”. Abbiamo così creato una nuova vista con la relativa classe che la gestisce, niente di più semplice!

2. Definiamo la prima vista

Entriamo, ora, nel file “viewTutorialViewController.h” e inseriamo le seguenti dichiarazioni:

Alla riga 6 abbiamo definito un elemento di tipo VistaDue, che sarà proprio la vista che caricheremo. Abbiamo, inoltre, definito anche un’azione “cambiaVista”, che assoceremo ad un pulsante, sarà l’evento che avvierà il cambio di vista.

Salviamo il file appena modificato e apriamo il file “viewTutorialViewController.xib”. In Interface Builder apriamo il Pannello dei documenti e inseriamo un elemento del tipo “UIViewController” al suo interno:

Selezioniamo il componente appena inserito e dal pannello Identity Inspector selezioniamo come classe “VistaDue”:

Ora inserite nella vista principale (non nel ViewController che abbiamo appena inserito) un bottone. Ecco come si presenta la mia vista:

Ora selezionate il File’s Owner. Dobbiamo collegare i due componenti che abbiamo definito poco fa. Colleghiamo l’azione “cambiaVista” con il bottone, selezionando “Touch Up Inside” quando appare il menù di scelta dell’azione. Collegate, infine, l’elemento “vistaDueController” con l’UIViewController che abbiamo inserito poco prima. Se avete eseguito tutto correttamente avrete un pannello che si presenta così:

Possiamo salvare e chiudere questa vista.

3. Definiamo la “VistaDue”

Dobbiamo ora definire la seconda vista. Apriamo per prima cosa il file “VistaDue.h” e definite semplicemente questa azione (riga 6):

Salvate il file e apriamo “VistaDue.xib”. Anche in questo caso inseriamo semplicemente un bottone nella vista, che ci permetterà di tornare alla prima vista:

Selezioniamo il File’s Owner e colleghiamo l’azione “tornaIndietro” con il bottone che abbiamo inserito, selezionando sempre “Touch Up Inside” come azione:

Salviamo e chiudiamo pure Interface Builder.

4. Scriviamo il codice necessario

Dobbiamo ora scrivere il codice che ci permetterà di passare da una vista all’altra. Vedrete che le istruzioni necessarie saranno davvero molto poche.

Apriamo il file “viewTutorialViewController.m” e inseriamo il seguente codice:

Alla riga 9 abbiamo inizializzato la vista, inserendo anche il nome del file .xib che deve essere caricato. La riga 10, invece, ci permette di impostare l’animazione del passaggio dalla prima alla seconda vista. Ci sono tre animazioni già predisposte e disponibili:

  • UIModalTransitionStyleCoverVertical, il caricamento della nuova vista sarà verticale, dal basso verso l’alto;
  • UIModalTransitionStyleFlipHorizontal, c’è la rotazione flip-side, ovvero come se venisse mostrato il retro della vista;
  • UIModalTransitionStyleCrossDissolve, dissolvenza incrociata.

L’ultima istruzione (riga 11) permette di mostrare la seconda vista, mostrandola così all’utente.

Ora non ci resta che definire il metodo “tornaIndietro” della classe VistaDue. Apriamo il file “VistaDue.m” e inseriamo la definizione del metodo:

Questa istruzione ci permette di uscire dalla vista corrente e tornare a quella che era visualizzata precedentemente (nel nostro caso la vista “viewTutorialViewController”).

Abbiamo concluso! Clicchiamo su “Build and Run” e controlliamo che l’applicazione funzioni correttamente!

Se Avete Problemi, questo è il nostro file di progetto.

La guida è stata scritta da Andrea Busi per “Bubi Devs“. I meriti, quindi, sono del legittimo autore.

Andrea Busi | @bubidevs

Laureato in Ingegneria Informatica, ho fondato nel 2008 questo piccolo blog, in cui racconto le mie esperienze e i miei pensieri sul mondo dell'informatica. Nella vita mi occupo di sviluppo software, e nel tempo libero continuo a coltivare la mia passione per il mondo iOS.

$ommenti a “DevTutorial #12 – Gestire più viste create con Interface Builder

  1. Simone ha detto:

    ciao, a me funziona ma dà un warning agli addsubview:
    passing argument1 of addsubview.

    è solo un mio problema?

  2. Andrea Busi ha detto:

    @Simone: ciao, io ho guardato il mio file di progetto e non c’è nessun warning.. Hai provato a confrontarlo con il tuo?

  3. Simone ha detto:

    Sì è uguale, apparentemente non mi dava warning, ma quando sono andato sul codice ho visto che ad ogni [self addsubview:viewN] mi dava questo warning,
    Ho provato a mettere self.view e viewN.view ma naturalmente visto che erano già view mi dava errore…
    Non capisco 🙁

  4. Simone ha detto:

    No Andrea, ho provato a riaprire il progetto ora, e mi sono accorto che sono scomparsi!!
    Incredibile ma vero!
    Alla creazione c’erano, ora non ci sono più! bo =)

    Un ultima cosa, mi daresti una dritta su come aggiungere lo splashscreen di cui hai fatto il tutorial prima della prima subview?
    Io ci ho provato modificando solamente il collegamento (viewcontroller = [[viewTutorialViewController alloc] init]) invece che initWithNibName…bundle..].
    Ma naturalmente non và, dopo lo splash screen non parte la mainview e quindi la prima subview ma si vede solo la finestra…

    Grazie, Simone.

  5. Andrea Busi ha detto:

    @Simone: ottimo, ogni tanto XCode da segni di pazzia!! 😉

    comunque per la SplashScreen posso guardarci appena ho un po’ di tempo.. Se ho novità ti faccio sapere!

  6. mecchi ha detto:

    Anche a me stesso problema di Simone, solo che quando riapro il warning persiste….

  7. matteo ha detto:

    ciao andrea,
    avrei una domanda. Ma se io avessi delle variabili di tipo int in VistaDue e creassi una VistaTre(e ci sono riuscito), come dovrei fare a recuperare le variabili?!…è da qualche giorno che ci provo ma non riesco proprio..mi ritornano sempre azzerate..probabilmente sbaglio nel recuperare l’istanza corretta di VistaDue che nell’esempio sarebbe “vistaDueController” giusto?!

    grazie mille!

  8. Andrea Busi ha detto:

    @matteo: penso che potresti trovare quello che ti serve in QUESTO tutorial

  9. enrico ha detto:

    bello….ma per creare un progetto a più viste per mac e non per iphone come mi muovo??…
    Grazie

  10. Andrea Busi ha detto:

    @enrico: purtroppo non saprei, non mi sono mai cimentato nello sviluppo di applicazioni per Mac ;(

  11. adriano ha detto:

    ciao, io faccio come descritto , ci ho provato più di una volta, ma dal momento che faccio doppio click sul file .xib non mi apre la library per l’ interfaccia grafica… cosa devo fare? ti ringrazio

  12. Andrea Busi ha detto:

    @adriano: se non vedi la libreria ti basta fare “Tools -> Library” e apparirà 😉

  13. ale ha detto:

    ciao! prima di tutto complimenti per la guida, mi è stata molto d’aiuto!
    ho però un dubbio:
    se volessi togliere l’effetto di transizione tra le due viste mi basta togliere questa riga di codice?
    vistaDueController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;

    grazie!

  14. Andrea Busi ha detto:

    @ale: ciao, no, non è quella da modificare.. ovvero, se la togli fa ugualmente un’animazione di default.. devi cambiare questa istruzione:

    devi solo cambiare il valore del parametro “animated” da YES a NO 😉

  15. fabri ha detto:

    buongiorno a tutti e complimenti per la guida.

    Ho seguito il tutorial e tutto funziona perfettamente. Il passo successivo è stato quello di aggiungere un’altra finestra per capire se avevo “appreso” la tecnica di collegare le varie viste tra di loro ma mi è capitato un problema sulla seconda vista

    se dalla prima vado alla seconda e viceversa tutto funziona, se dalla prima vado alla terza e viceversa tutto funziona, ma se dalla seconda voglio passare alla terza và in crash e si chiude.

    Qualcuno saprebbe dirmi dove può essere l’errore???

    grazie in anticipo e scusate il poema ma sono un povero novellino perso nel mare di”Xcode” 🙂

  16. fabri ha detto:

    ci ho riprovato ma non riesco ad aggiungere una terza vista..:-(

    Se volessi aggiungere una terza e una quarta vista, in modo da poterle collegare tra loro, devo seguire sempre questo metodo???

    spero che qualche anima pia mi aiuti

  17. fabri ha detto:

    @fabri: @fabri:

    Forse sono stato poco chiaro, cerco di spiegarmi meglio

    Diaciamo che ho due viste, ne voglio creare una terza (conteneti le info e i ringraziamenti). come posso fare per poter richiamare la vista info da entrambe le viste?

    PS grazie in anticipo 🙂

  18. Andrea Busi ha detto:

    @fabri: segui lo stesso procedimento.. se non vuoi istanziare una nuova vista info ti basterà passare lo stesso riferimento nelle varie classi, come se passasi una normale variabile..

  19. fabri ha detto:

    ok ci provo e ti faccio sapere, grazie mille

  20. fabri ha detto:

    @fabri:

    Funziona!!!!!! 🙂

    grazie mille per la dritta

  21. Lorenzo ha detto:

    Gran bel articolo. Funziona tutto 🙂

    Se volessi replicare questa funzionalità, però usando un Navigation Controller ?

    Mi spiego meglio:

    ho i seguenti file .xib:
    MainWindow: Contiene il Navigation Controller
    Il ViewController del Navigation Controller l’ho associato al NIB File: HomeViewController.
    Nel file.xib HomeViewController è presente una view con un pulsante. Questo pulsante deve aprire un’altra view contenuta in un altro file .xib.

    Vorrei far in modo che quando clicco sul pulsante si apra la view (come avviene in questa guida) e di conseguenza possa tornare indietro sfruttando il navigation Controller.

  22. Kevin ha detto:

    Raga a me da errore… io ho cambiato leggermente i nomi e non capisco dove ho sbagliato…

    2011-03-30 21:04:05.464 viewTutorial[725:207] *** Terminating app due to uncaught exception ‘NSInternalInconsistencyException’, reason: ‘Could not load NIB in bundle: ‘NSBundle (loaded)’ with name ‘Vista2”

    eccezione alla riga:
    vista2controller = [[Vista2 alloc] initWithNibName:@”Vista2″ bundle:nil];

    credo sia il nib name! Consigli?

  23. Kevin ha detto:

    Ho risolto. Mancava il file xib! scusatemi

  24. Andrea Busi ha detto:

    @Kevin: l’avevo immaginato ;).. hai risolto da solo, meglio ancora 😛

  25. Lorenzo ha detto:

    Ciao,

    Le tre animazioni sopra citate possono essere aggiunte anche con un Navigation Controller ?

  26. Andrea Busi ha detto:

    @Lorenzo: no, se utilizzi un UINavigationController queste animazioni non sono possibili..

  27. tommaso ha detto:

    posso fare lo stesso procedimento per gestire una vista da una toolbar?

  28. Andrea Busi ha detto:

    @tommaso: si puoi utilizzare senza problemi questo procedimento 😉

  29. Bianconi Luca ha detto:

    Ciao il tutorial perfetto solo un problema con ios 4.3 , ho un uibutton sulla prima vista che carica una seconda passando @”nibfile” carico la seconda vista che ha un UIscroll che contiene un UItextView e un uibutton per tornare alla vista principale tutto ok funziona tutto ma se chiudo con home e poi riapro l’app se provo a fare qst operazioni mi va in errore sulla riga

    – (IBAction)tornaIndietro{
    [[self parentViewController] dismissModalViewControllerAnimated:YES];
    }
    quale puo’essere il problema ?
    ciao e grazie sei un mito 🙂

  30. Andrea Busi ha detto:

    @Luca: strano come problema, riesci a postare l’errore che ti viene restituito? così vediamo cosa può essere 😉

  31. Alberto ha detto:

    Ho copiato la tua guida per una mia App : il problema è il ritorno dalla seconda alla prima.
    In pratica mi da errore su :
    [[self parentViewController] dismissModalViewControllerAnimated:YES];

    e l’errore è : instance method -dismissModalViewControllerAnimated not found (return type defaults to ‘id’)

  32. Andrea Busi ha detto:

    @Alberto:
    prova semplicemente con

    Se il tuo controller è una sottoclasse di UIViewController non dovrebbe darti errori..

  33. Andrea ha detto:

    Ciao a tutti,

    forse sono un po’ in ritardo.. a me non funziona.

    Va si sulla seconda vista ma quando seleziono sulla 2 “Torna alla prima vista” non accade nulla.

  34. Andrea Busi ha detto:

    @Andrea:
    dovrebbe essere “colpa” di iOS 5, prova ad utilizzare l’istruzione

    per tornare alla prima vista, dovrebbe funzionare 😉

  35. Enrico ha detto:

    Ciao, intanto complimenti.

    Volevo chiedervi se era possibile utilizzare per il cambio vista invece che il “button” il semplice scorrere dell’indice (con gesti).

    Grazie

  36. Andrea ha detto:

    Ciao Andrea!
    Io ho un problema…anche se è solo un warning…ho usato il tuo spunto per fare un progetto mio…
    nella riga di codice seguente

    [self dismissModalViewControllerAnimated:YES];

    mi dice “dismissModalViewControllerAnimated” is deprecated…

    Come posso risolvere?

    Altro warning invece con la riga di codice del mio progetto

    RistController = [[RistViewController alloc] initWithNibName:@”RistViewController” bundle:nil];

    qui mi dice “incompatible pointer assignment to…”

    potresti darmi una mano?

    Grazie mille!!

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

*