2012-04-12 10 views
5

ho un NSDictionary che diremo è come questo:Molti UITableViewCells differenti in una TableView

key:  value: 
name  Bookshelf 
movies  Array containing: (Movie 1, Movie 2, Movie 3) 
books  Array containing: (Book 1, Book 2, Book 3) 
music  Array containing: (Music 1, Music 2, Music 3) 

E così via. Ora quello che sto cercando di fare è creare una tabellaView che mostri tutte queste informazioni, ma con diversi tipi di celle in base a quale sia la chiave del dizionario. Ad esempio, i film utilizzano i libri cellForMovies utilizzano l'uso di musica cellForBookscellForMusic, ognuno ha il proprio layout.

Ovviamente, sto semplificando eccessivamente, ma spero che capiate cosa sto cercando di fare.

Sono in grado di farlo se faccio sezioni e un tipo di cella diverso per ogni sezione, ma non voglio farlo. Voglio essere in grado di avere una tabella come questa, per esempio:

cellForBooks 
cellForMovies 
cellForMovies 
cellForMusic 
cellForBooks 

e così via ... Tutte le idee o le risorse mi consente di puntare? Mi interessa solo il supporto per iOS 5 (storyboard).

Edit con la soluzione:

Un grande ringraziamento a tutti coloro che hanno contribuito, in particolare atticus che ha messo insieme il pezzo finale.

Ciò che ha finito per funzionare è stato quello di modificare la struttura dei dati in modo che fosse una matrice di dizionari e quindi aggiungere un Key: type Value: book/movie/music a ciascuna voce. La struttura dei dati ora si presenta come:

Array[0]: Dictionary: [Key: type Value: book], [Key: name Value: Physics]; 
Array[1]: Dictionary: [Key: type Value: music], [Key: name Value: Rock]; 

Poi per configurare le cellule che ho fatto questo:

NSString *CellIdentifier = @"Cell"; 
NSDictionary *object = [self.listOfStuff objectAtIndex:indexPath.row]; 
if ([[object objectForKey:@"type"] isEqualToString:@"book"]){ 
    CellIdentifier = @"BookCell"; 
}else if ([[object objectForKey:@"type"] isEqualToString:@"music"]){ 
    CellIdentifier = @"MusicCell"; 
}else if ([[object objectForKey:@"type"] isEqualToString:@"movie"]){ 
    CellIdentifier = @"MovieCell"; 
} 

ognuno di questi ha avuto un tableviewcell diverso nella storyboard. Abbiamo capito se si desidera utilizzare una delle funzioni cellulari incorporati, come cell.textLabel.text avevi bisogno di fare questo:

cell.textLabel.text = [object objectForKey:@"name"]; 
cell.textLabel.backgroundColor = [UIColor clearColor]; 
cell.textLabel.opaque = NO; 

Spero che questo aiuti qualcun altro in futuro.

+0

C'è uno storyboard da qualche parte? Non ne vedo uno nel repository. – atticus

+0

È stato localizzato per qualche motivo. È nella directory en.lprog. –

+1

Capito. Va tutto bene, tranne che stai usando la proprietà textLabel integrata nella cella personalizzata. Quando lo si imposta, la cella si nasconde e il colore di sfondo dell'etichetta è bianco fisso. Quando selezioni la cella, rende temporaneamente lo sfondo trasparente e puoi vedere gli elementi dietro di esso. Se si desidera utilizzare la textLabel integrata, è sufficiente impostare il colore di sfondo per cancellare: \t 'cell.textLabel.backgroundColor = [UIColor clearColor]; cell.textLabel.opaque = NO; ' – atticus

risposta

6

Un grande ringraziamento a tutti coloro che hanno contribuito, in particolare atticus che ha messo insieme il pezzo finale.

Ciò che ha finito per funzionare è stato quello di modificare la struttura dei dati in modo che fosse una matrice di dizionari e quindi aggiungere un Key: type Value: book/movie/music a ciascuna voce. La struttura dei dati ora si presenta come:

Array[0]: Dictionary: [Key: type Value: book], [Key: name Value: Physics]; 
Array[1]: Dictionary: [Key: type Value: music], [Key: name Value: Rock]; 

Poi per configurare le cellule che ho fatto questo:

NSString *CellIdentifier = @"Cell"; 
NSDictionary *object = [self.listOfStuff objectAtIndex:indexPath.row]; 
if ([[object objectForKey:@"type"] isEqualToString:@"book"]){ 
    CellIdentifier = @"BookCell"; 
}else if ([[object objectForKey:@"type"] isEqualToString:@"music"]){ 
    CellIdentifier = @"MusicCell"; 
}else if ([[object objectForKey:@"type"] isEqualToString:@"movie"]){ 
    CellIdentifier = @"MovieCell"; 
} 

ognuno di questi ha avuto un tableviewcell diverso nella storyboard. Abbiamo capito se si desidera utilizzare una delle funzioni cellulari incorporati, come cell.textLabel.text avevi bisogno di fare questo:

cell.textLabel.text = [object objectForKey:@"name"]; 
cell.textLabel.backgroundColor = [UIColor clearColor]; 
cell.textLabel.opaque = NO; 

Spero che questo aiuti qualcun altro in futuro.

6

Nel metodo - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath è possibile restituire molti tipi di celle in base a indexPath.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    if (indexPath.row > 5) { // Your conditions here to choose between Books and Movies 
     BookCell *cell = [tableView dequeueReusableCellWithIdentifier:@"bookCell"]; 
     if (!cell) 
     { 
      cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault  reuseIdentifier:@"bookCell"]; 
     } 
     return cell; 
    } else { 
     MovieCell *cell = [tableView dequeueReusableCellWithIdentifier:@"movieCell"]; 
     if (!cell) 
     { 
      cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault  reuseIdentifier:@"movieCell"]; 
     } 
     return cell; 
    } 
return nil; 
} 
+2

In iOS 5 con gli storyboard non è necessario eseguire il controllo di una cella zero e istanziare più. -dequeueReusableCellWithIdentifier: si prenderà cura di questo per te. – atticus

+0

Se si restituisce nil da tableView: cellForRowAtIndexPath, l'app si arresterà in modo anomalo. Dovresti restituire qualcosa alla fine. Nel tuo caso, non riesci mai a superare il se/else quindi va bene, ma qualcosa a cui prestare attenzione. – atticus

+0

È possibile utilizzare alcuni typecasting per evitare di restituire 'nil'. Per quanto riguarda il tuo primo commento, puoi usare gli storyboard, ma ciò non significa che non puoi creare un'istanza di UITableView nel codice o sottoclasse UITableViewController. Quindi il controllo di 'nil' dopo' dequeueReusableCellWithIdentifier' potrebbe essere utile, dal momento che 'dequeueReusableCellWithIdentifier' può ancora restituire' nil' – anticyclope

0

La mia opinione è che è necessario implementare tutti i tipi di cella in una cella. Il che significa che dovresti avere una classe UITableViewCell e .xib per tutti loro. Quindi, in cellForRowAtIndexPath, crea la cella, quindi in base ai requisiti effettivi, mostra/nascondi i sottoview che costituiscono un libro o un film.

In tale progettazione, la tua cella sarà un po 'pesante. Tuttavia, è ancora meglio dell'utilizzo di più classi di celle perché in questo modo il riutilizzo delle celle è più efficiente ([UITableView dequeueReusableCellWithIdentifier]).

Credo che UITableView sia progettato per un tipo di cella. Quindi, se il tuo layout varia, puoi comunque metterli in un posto e usare frame o show/hide per controllare il comportamento delle celle.

+0

Utilizzando gli storyboard, è possibile creare più tipi di celle e rendere il codice molto più leggibile. – atticus

+0

Sono d'accordo @atticus. Ho provato questo metodo e rende lo scrolling un po 'lento perché ci sono molte ricchezze sul subview. Ho finito per ricreare le mie lezioni. Avere molte classi di riciclaggio nel cellForRowAtIndexPath rende lo scorrimento della tabella più semplice e veloce. –

3

Nello storyboard, impostare tableView per utilizzare Prototipi dinamici. Quindi, crea una cella per ogni tipo di cella che utilizzerai. Personalizza quelli appropriatamente, quindi dai a ciascuno un identificatore di riutilizzo unico nell'ispettore (ad esempio MovieCell).

Quindi, nella tabella: cellForRowAtIndexPath: metodo, determinare il tipo appropriato di cella per il contenuto in quel percorso dell'indice. Se la cella a indexPath dovrebbe essere una cellula di film, si crea il cellulare in:

static NSString * MovieCellIdentifier = @"MovieCell"; // This must match the storyboard 
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MovieCellIdentifier]; 

che vi darà la cella specificato come "MovieCell" nel tuo storyboard. Se è necessario personalizzarlo ulteriormente, creare una sottoclasse UITableViewCell e specificarlo per la cella in Storyboard. Quindi, è possibile fare riferimento alle proprietà ecc qui per la personalizzazione dalla fusione della cellula tornato:

MovieTableViewCell *movieCell = (MovieTableViewCell *)cell; 
// customize 
+0

Una domanda: alla fine della funzione cellForRowAtIndexPath, quale cella verrà restituita? Coz hai molti Tableviewcell personalizzati, ad es. MovieTableViewCell, BookTableViewCell ... Come li restituirai alla fine? –

0

credo u dovrebbe utilizzare il seguente come l'identificativo della cella.

- (UITableViewCell *)tableView:(UITableView *)tmpTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ 
NSString *cellIdentifier   = [NSString stringWithFormat:@"Cell%d%d",indexPath.section,indexPath.row]; 
UITableViewCell *cell    = [tmpTableView dequeueReusableCellWithIdentifier:cellIdentifier]; 
if (nil == cell) { 
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease]; 

// do ur stuff here 

} 
return cell; 
} 
Problemi correlati