2012-04-12 13 views
5

que tienen un NSDictionary que vamos a decir es la siguiente:UITableViewCells diferentes en un 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) 

Y así sucesivamente. Ahora lo que intento hacer es crear un TableView que muestre toda esta información, pero con diferentes tipos de celdas en función de la clave del diccionario. Por ejemplo, las películas usan cellForMovies libros usan cellForBooks música usan cellForMusic, cada uno tiene su propio diseño.

Obviamente, estoy simplificando demasiado, pero espero que entiendas lo que estoy tratando de hacer.

Soy capaz de lograr esto si hago secciones y un tipo de celda diferente para cada sección, pero no quiero hacer eso. Quiero ser capaz de tener una tabla de este modo, por ejemplo:

cellForBooks 
cellForMovies 
cellForMovies 
cellForMusic 
cellForBooks 

y así sucesivamente ... Cualquier idea o recursos que me puede apuntar a? Solo me importa el soporte de iOS 5 (guiones gráficos).

Editar con solución:

Un gran agradecimiento a todos los que ayudaron, especialmente Atticus que puso la última pieza juntos.

Lo que terminó funcionando fue cambiar la estructura de los datos para ser una matriz de diccionarios y luego agregar un Key: type Value: book/movie/music a cada entrada. La estructura de datos ahora queda como:

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

continuación para configurar las células que hice esto:

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"; 
} 

cada uno de ellos tenía un tableviewcell diferente en el guión gráfico. Nos dimos cuenta de que si quieres usar cualquiera de las funciones celulares incorporados, como cell.textLabel.text que tenía que hacer esto:

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

Espero que esto ayude a alguien más en el futuro.

+0

¿Hay un guión gráfico en alguna parte? No veo uno en el repositorio. – atticus

+0

Se localizó por alguna razón. Está en el directorio en.lprog. –

+1

Lo tengo. Todo está bien, excepto que está usando la propiedad incorporada textLabel en la celda personalizada. Cuando lo configura, la celda lo oculta y el color de fondo de la etiqueta es blanco sólido. Cuando selecciona la celda, borra temporalmente el fondo y puede ver los elementos detrás de ella. Si desea utilizar la etiqueta de texto incorporada que está bien, simplemente configure el color de fondo para borrar: \t 'cell.textLabel.backgroundColor = [UIColor clearColor]; cell.textLabel.opaque = NO; ' – atticus

Respuesta

6

Muchísimas gracias a todos los que ayudaron, especialmente a los áticos que juntaron la pieza final.

Lo que terminó funcionando fue cambiar la estructura de los datos para ser una matriz de diccionarios y luego agregar un Key: type Value: book/movie/music a cada entrada. La estructura de datos ahora queda como:

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

continuación para configurar las células que hice esto:

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"; 
} 

cada uno de ellos tenía un tableviewcell diferente en el guión gráfico. Nos dimos cuenta de que si quieres usar cualquiera de las funciones celulares incorporados, como cell.textLabel.text que tenía que hacer esto:

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

Espero que esto ayude a alguien más en el futuro.

6

En su método - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath puede devolver muchos tipos de celdas de acuerdo con 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

En iOS 5 con guiones gráficos no es necesario realizar el control de una celda nula y crear una instancia más. -dequeueReusableCellWithIdentifier: se encargará de eso por ti. – atticus

+0

Si devuelve nil desde tableView: cellForRowAtIndexPath, su aplicación se bloqueará. Deberías devolver algo al final. En tu caso, nunca superas el if/else, así que está bien, pero hay que tener cuidado. – atticus

+0

Puede usar algunos tipos de conversión para evitar devolver 'nil'. En cuanto a su primer comentario, puede usar guiones gráficos, pero no significa que no pueda crear una instancia de UITableView en el código, o la subclase UITableViewController. Así que la comprobación de 'nil' después de' dequeueReusableCellWithIdentifier' podría ser útil, ya que 'dequeueReusableCellWithIdentifier' aún puede devolver' nil' – anticyclope

0

Mi opinión es que debe implementar todos sus tipos de células en una sola célula. Lo que significa que debe tener una clase UITableViewCell y .xib para todas ellas. Luego, en cellForRowAtIndexPath, cree la celda y luego, según el requisito real, muestre/oculte las subvistas que conforman un libro o una película.

En dicho diseño, su celda será algo pesada. Sin embargo, sigue siendo mejor que usar varias clases de celdas porque de esta manera la reutilización de celdas es más eficiente ([UITableView dequeueReusableCellWithIdentifier]).

Creo que UITableView está diseñado para un tipo de celular. Por lo tanto, si su diseño varía, puede ponerlos en un solo lugar y usar frame o show/hide para controlar el comportamiento de la celda.

+0

Al utilizar guiones gráficos, está bien crear varios tipos de celdas y hace que el código sea mucho más legible. – atticus

+0

Estoy de acuerdo @atticus. Probé este método y hace que el desplazamiento se retrase un poco porque hay muchas subvistas de reciclaje. Terminé recreando mis clases. Tener muchas clases reciclando en el cellForRowAtIndexPath hace que el desplazamiento de la tabla sea más suave y rápido. –

3

En su guión gráfico, establezca tableView para usar prototipos dinámicos. Luego, crea una celda para cada tipo de celda que vas a usar. Personalícelos adecuadamente y luego dé a cada uno un identificador de reutilización único en el inspector (por ejemplo, MovieCell).

Luego, en su método tableview: cellForRowAtIndexPath: determine el tipo de celda apropiado para el contenido en esa ruta de índice. Si la celda en indexPath debe ser una célula película, que crearía la célula usando:

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

que le dará la célula que ha especificado como "MovieCell" en su guión. Si necesita personalizarlo aún más, cree una subclase UITableViewCell y especifique eso para la celda en Storyboard. A continuación, puede hacer referencia a las propiedades, etc. aquí para la personalización echando la célula devuelto:

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

Una pregunta: al final de la función cellForRowAtIndexPath, ¿qué celda se devolverá? Porque tienes muchas TableViewcell personalizadas, p. MovieTableViewCell, BookTableViewCell ... ¿Cómo los devolverá al final? –

0

creo que u debe utilizar lo siguiente como su identificador de celda.

- (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; 
} 
Cuestiones relacionadas