• DevTutorial
  • Libro
  • Guide Mac
  • Giovedi Contest

DevTutorial #18 – TabBar Application, parte 2: inseriamo una NavigationBar

The AuthorAndrea Busi The Time11 luglio 2009 Comments22
separator

Eccoci con il secondo tutorial dedicato alle TabBar. Nella prima lezione abbiamo visto come creare una struttura generale, composta da due sezioni. Oggi vedremo, invece, come inserire una UINavigationBar all’interno di una nuova sezione, e gestire il movimento tra le varie celle di una tabella. Ovvero, quando l’utente seleziona una determinata cella si aprirà una corrispondente vista che avremo definito con Interface Builder. La navigation bar, poi, ci permetterà di tornare alla tabella principale. Un po’ come avviene nel menù “Impostazioni” del’iPhone / iPod Touch!

Buon tutorial a tutti!

1. Creiamo un nuovo elemento per la TabBar

Iniziamo creando la classe che gestirà la nuova vista. Dal menù “File” scegliamo “New File…”, nel pannello che apparirà selezioniamo “UIViewController subclass” e chiamiamo questa nuova classe “TabellaController”.

Immagine 1

Abbiamo già imparato a gestire una tabella in questa serie di tutorial, quindi non rispiegherò il codice utilizzato. Riutilizziamo gli stessi metodi, quindi inserite nel file “TabellaController.h” il seguente codice:

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

Mentre in “TabellaController.m” inserite questi metodi:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#import "TabellaController.h"
 
@implementation TabellaController
 
@synthesize lista;
 
- (void)awakeFromNib{
	// creiamo la lista e inseriamo una serie di elementi da visualizzare nella nostra tabella
	lista = [[NSArray alloc] initWithObjects:	@"iPhone", @"iPod", @"iPod Touch", @"iMac", @"iBook",
			 @"MacBook", @"MacBook Pro", @"Mac Pro", @"PowerBook", nil];
 
}
 
//setta il numero di sezioni della tabella
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
	return 1;
}
 
//setta il numero di righe della tabella
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
	//il numero di righe deve corrispondere al numero di elementi della lista
	return [lista count];
}
 
//settiamo il contenuto delle varie celle
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
 
	UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cellID"];
 
	if (cell == nil){
		cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:@"cellID"] autorelease];
 
	}
 
	//inseriamo nella cello l'elemento della lista corrispondente
	cell.textLabel.text = [lista objectAtIndex:indexPath.row];
 
	return cell;
}

Insomma, la classica gestione delle UITableView

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

2. Definiamo l’aspetto del nuovo elemento

Dalla Libreria prendiamo un componente UINavigationController e inseriamolo nella tab bar, proprio come abbiamo fatto nello scorso tutorial per le due viste.

Immagine 4

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

Immagine 5

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

Immagine 6

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

Immagine 7

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

Immagine 8

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

Immagine 9

3. Implementiamo due viste di dettaglio

Ora vediamo di analizzare un aspetto che molti utenti mi hanno chiesto via mail. Se noi volessimo associare un determinato file “xib” (ovvero creato con Interface Builder) ad una cella, come potremmo fare? In questa seconda parte del tutorial vedremo proprio di analizzare i passaggi necessari. Andremo a definire due viste, una che conterrà una foto dell’elemento “iPhone”, mentre un’altra che avviserà l’utente dell’assenza di informazioni per un determinato prodotto. Ovviamente potreste realizzare una vista con i dettagli per ogni prodotto presente nella tabella, ma il meccanismo rimane invariato.

Iniziamo creando due nuovi file xib, dal menù “File -> New File…” e scegliendo “Empty XIB”. Io ho chiamato il primo file “iPhoneDetail” e il secondo “OtherDetail”, ma nulla vieta di chiamarli in modo diverso!

Immagine 10

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

Immagine 11

Possiamo spostare i file appena creati nella sezione “Classes” del nostro progetto, per avere un risultato come questo:

Immagine 12

Ora siamo pronti per definire l’aspetto di queste due nuove viste.

4. Definiamo l’aspetto grafico delle due viste di dettaglio

Apriamo il file “iPhoneDetail.xib” in Interface Builder. Il procedimento è, come già detto, uguale a quello svolto per la definizione delle due viste “PrimaVista” e “SecondaVista”. Inseriamo, quindi, un componente UIView nel Pannello dei Documenti e modifichiamolo a nostro piacimento. Ecco come risulta essere la mia vista:

Immagine 11

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

Immagine 12

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

Immagine 15

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

Immagine 16

Possiamo salvare tutto e chiudere Interface Builder.

5. Come richiamare le due viste via codice

Ora non ci resta che analizzare il codice che ci permette di aprire queste due viste. Apriamo il file “TabellaController.h” e modifichiamolo nella seguente maniera:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#import <UIKit/UIKit.h>
#import "iPhoneDetailController.h"
#import "OtherDetailController.h"
 
@interface TabellaController : UITableViewController {
	//array che conterrà gli elementi da visualizzare nella tabella
	NSArray *lista;
 
	//controller della vista che dovrà essere aperta
	UIViewController *detail;
}
 
@property (nonatomic, retain) NSArray *lista;
 
@end

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

Ora apriamo il file “TabellaController.m” e inseriamo il metodo che viene richiamato quando si clicca su una cella:

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

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

Abbiamo concluso!! Clicchiamo su “Build and Go!” e godiamoci la nostra applicazione funzionante!!

Immagine 19

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

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

separator
Condividi su FriendFeed
separator
Comments
22 Comments
separator
  1. luigi

    Salve,
    ho seguito alla perfezione la Vs. guida ma non capisco perche non visualizzo la tabella, nemmeno quella di default ( ovviamente parlo nel momento in cui effettuo il build dell’applicazione )
    Non riesco a capire dove sbaglio…

    ReplicaReplica
  2. Andrea Busi

    @luigi: ciao..
    detto così non saprei.. se vuoi inviami il progetto così provo a vedere se trovo l’inghippo..

    ReplicaReplica
  3. luigi

    @Andrea Busi: mi dai una tua mail? puoi anche scrivermi a marino_luigi@hotmail.com
    grazie

    ReplicaReplica
  4. Nantas

    Stranamente, quando scarico il tuo progetto e provo a compilarlo, mi da un errore generale (there is non SDK with specified name or path “unknown path”).
    Sapresti spiegarmi il perchè?

    ReplicaReplica
  5. Andrea Busi

    @Nantas: controlla se nelle impostazioni del progetto è selezionata la versione corretta dell’SDK..

    ReplicaReplica
  6. Marco Taglioni

    Ciao.
    Qualcuno mi può spiegare come fare in modo che invece di una finestra di dettaglio mi si apra un’altra tabella?
    Io seguo la guida e riesco a far apparire la tabella solo che non riesco a farci apparire dentro nessun elemento

    ReplicaReplica
  7. Andrea Busi

    @Marco Taglioni: probabilmente non hai inserito la definizione della lista nel metodo esatto.. prova ad usare il metodo “viewWillAppear” e inizializzare li la lista con gli elementi ;-)

    ReplicaReplica
  8. Marco Taglioni

    2010-02-25 15:48:08.962 Assurdo![7239:207] *** Terminating app due to uncaught exception ‘NSInternalInconsistencyException’, reason: ‘-[UIViewController _loadViewFromNibNamed:bundle:] loaded the “PrimaCategoria” nib but the view outlet was not set.’

    questo è l’errore che ho.
    la vista l’ho creata usando un UINavigationController con dentro un UITableViewController.

    i

    ReplicaReplica
  9. Andrea Busi

    @Marco Taglioni: hai dimenticato di collegare il componente “view” in Interface Builder ;-)

    ReplicaReplica
  10. tonyangelo

    Grazie milla dell’ottima guida!

    Io volevo capire se per mettere una tableview invece di una detailview come dice Marco, quando apro il nib devo prima mettere una uiview e poi sopra una tableview o direttamente una tableview?Grazie Andrea
    Perchè io l’ho fatto e nella console non mi da neanche errori solo che appena seleziono la prima cella va in crash l’app :(

    ReplicaReplica
  11. Andrea Busi

    @tonyangelo: penso che basti inserire solo una UITableView.. se vuoi mandami il progetto via mail, così provo a vedere dove è l’errore e poi ti dico ;-)

    ReplicaReplica
  12. pn

    ciao andrea,
    innanzitutto complimenti per le ottime guide che scrivi!

    avrei una domanda di pura curiosità: nel file TabellaController.m dopo aver rilasciato detail, lo setti a nil. perché fai questo? se l’hai rilasciato non dovrebbe essere sufficiente?

    grazie mille!
    pierre

    ReplicaReplica
  13. iCiccio

    CIao,
    ho seguito questo tutorial per realizzare una mini applicazione per un mio sito, solo che quando clicco sulla riga va in crash, non capisco dove sta l’errore puoi aiutarmi? se è possibile ti mando il pacchetto completo via email e me lo verifichi magari potresti darmi anche qualche consiglio ciao!!!

    ReplicaReplica
  14. Andrea Busi

    @iCiccio: certo, inviamelo pure a bubidevs at gmail dot com ;)

    ReplicaReplica
  15. iCiccio

    Ciao Andrea ho risolto da me, il mio problema adesso è che avrei una lista di diverse voci, tutte fanno capo ad un sto web quindi con una UIViewWeb sto creando le varie schermate, per intenderci le varie pagine del sito (Redazione, Chi siamo, collabora etc etc) ovviamente con questa parte di codice riesco a gestire se l’utente ha selezionato una riga della tabella, visto che sono circa 5 come devo implementare il codice di seguito riportato?

    // Metodo relativo alla selezione di una cella
    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

    if (indexPath.row == 0){
    //l’utente ha cliccato sull’elemento iPhone, quindi carichiamo la vista relativa
    detail = [[ChiSiamoController alloc] initWithNibName:@”ChiSiamo” bundle:[NSBundle mainBundle]];
    } else {
    detail = [[RedazioneController alloc] initWithNibName:@”Redazione” bundle:[NSBundle mainBundle]];
    }

    //Facciamo visualizzare la vista con i dettagli
    [self.navigationController pushViewController:detail animated:YES];
    //rilasciamo il controller
    [detail release];

    detail = nil;
    }

    Grazie infinite per il tuo aiuto, cmq ti mando via email il mio progettino, magari se me lo verifichi mi dici se sto procedendo correttamente oppure che alternativa ci sarebbe per la tipologia di applicazione che voglio creare (gratuita), ti scrivo tutto nella mail.

    ciao!!!!

    ReplicaReplica
  16. marco

    ciao andrea…Seenti…io Avrei bisogno di creare una di app tab-bar…con 1 vista e 2 tabelle ho bisogno…ma intanto stavo provando con una…come mai ho fatto tutti i passaggi,ho collegato tutto ma quando lancio l’app mi mostra prodotti apple in alto, ma la tabella vuota???=(

    ReplicaReplica
  17. Smaramba

    Ciao, scusate io avrei un piccolo problemino…prendendo spunto da questa guida ho ricreato un tap bar con tabella solo che ho diviso la lista degli elementi in sezioni..(creando ovviamente apposite array e dict)…fin qui tutto bene…ho diviso le sezioni utilizzando uno Switch creando appunto 4 “case”….
    adesso dovrei associare vari file xib(in modo da creare piu finestre) alle relative celle…ho utilizzato questa stringa :
    if (indexPath.row == 0){
    //l’utente ha cliccato sull’elemento iPhone, quindi carichiamo la vista relativa
    detail = [[iPhoneDetailController alloc] initWithNibName:@”iPhoneDetail” bundle:[NSBundle mainBundle]];
    } else …
    aggiungendone tante quante le celle…scoprendo pero il problema…il row indicato(che sia 0,1,2) non si riferisce alla prima,seconda ecc, cella, ma ALLA 1A CELLA DI OGNI SEZIONE….associandomi quindi 1 xib per per ogni 1 cella di ogni sezione…allora ho fatto una modifica….che pero mi si è rivoltata contro:

    if (indexPath.section == 0, indexPath.row == 0){
    detail = [[NOME FIEL XIB alloc] initWithNibName:@”NOME FIEL XIB” bundle:[NSBundle mainBundle]];
    } else if (indexPath.section == 0, indexPath.row == 1 ){
    detail = [[NOME FIEL XIB alloc] initWithNibName:@”NOME FIEL XIB” bundle:[NSBundle mainBundle]];

    in questo modo ho pensato che associasse il determinato xib alla SEZIONE da me indicata e alla CELLA da me indicata…mi associa quest’ordine a tutte le sezioni….credo sicuramente di aver sbagliato……HELP

    PS.scusate la mia “scrittura”….help help help

    ReplicaReplica
  18. Max

    ciao. mi chiedevo se è possibile inserire il terzo tab in un nib separato o se è per forza necessario inserirlo all’interno di quello principale.

    mi sembra che separarlo sia meglio dal punto di vista architetturale

    ReplicaReplica
  19. Andrea Busi

    @Max: no tranquillo, puoi anche inserirlo in uno xib diverso, anzi, forse è la soluzione più corretta ;)

    ReplicaReplica
  20. help

    Salve a tutti Andrea ho bisogno di aiuto non riesco a far girare l’applicazione mi dice errore
    error: There is no SDK with the name or path ‘iphoneos3.0′
    non so piu che fare grazie mille ti posso contattare per mail eventualmente

    ReplicaReplica
  21. Andrea Busi

    @help: ciao, c’è qualcosa nelle proprietà progetto da modificare.. controlla che sia settato tutto su iOS 4, casomai se non riesci inviami pure il progetto via mail..

    ReplicaReplica
separator
A chi è piaciuto questo articolo?
  1. DevTutorial #18 – TabBar Application, parte 2: inseriamo una NavigationBar
separator

Scrivi la tua!

© 2010 Bubi Devs. Powered by WordPress Designed by miniMAC
w3c Made in Mac