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:

#import <UIKit/UIKit.h>

@class VistaDue;

@interface viewTutorialViewController : UIViewController {
	IBOutlet VistaDue *vistaDueController;
}

@property (nonatomic, retain) IBOutlet VistaDue *vistaDueController;

-(IBAction)cambiaVista;

@end

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):

#import <UIKit/UIKit.h>

@interface VistaDue : UIViewController {
}

-(IBAction)tornaIndietro;

@end

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:

#import "viewTutorialViewController.h"
#import "VistaDue.h"

@implementation viewTutorialViewController

@synthesize vistaDueController;

-(IBAction)cambiaVista{
	vistaDueController = [[VistaDue alloc] initWithNibName:@"VistaDue" bundle:nil];
	vistaDueController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
	[self presentModalViewController:self.vistaDueController animated:YES];
}

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:

- (IBAction)tornaIndietro{
	[[self parentViewController] dismissModalViewControllerAnimated:YES];
}

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.

Ingegnere informatico e sviluppatore freelance, mi occupo da anni di sviluppo per iOS (ma non solo). Dal 2008 scrivo su questo piccolo blog (con qualche lunga pausa), in cui parlo di programmazione e di qualsiasi altra cosa che mi diverta.

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

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

    è solo un mio problema?

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

  • 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 🙁

  • 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.

  • @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!

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

  • 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!

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

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

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

  • 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

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

  • 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!

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

    [self presentModalViewController:self.vistaDueController animated:NO];

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

  • 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” 🙂

  • 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

  • @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 🙂

  • @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..

  • ok ci provo e ti faccio sapere, grazie mille

  • @fabri:

    Funziona!!!!!! 🙂

    grazie mille per la dritta

  • 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.

  • 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?

  • Ho risolto. Mancava il file xib! scusatemi

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

  • Ciao,

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

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

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

  • @tommaso: si puoi utilizzare senza problemi questo procedimento 😉

  • 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 🙂

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

  • 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’)

  • @Alberto:
    prova semplicemente con

    [self dismissModalViewControllerAnimated:YES];
    

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

  • 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.

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

    [self dismissModalViewControllerAnimated:YES];
    

    per tornare alla prima vista, dovrebbe funzionare 😉

  • 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

  • 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!!

Leave a Reply to tommaso Cancel Reply

Your email address will not be published.

Site Footer