2011-06-11 12 views
11


iOS de Apple TableView y la reutilización de células me está matando. Busqué, busqué y estudié, pero no puedo encontrar buenos documentos ni buenas respuestas. El problema es que cuando el TableView reutiliza celdas, las cosas como las Marcas de verificación (accesorio de la celda) configuradas en una Celda seleccionada se repiten en las celdas más abajo en la vista de tabla. Entiendo que la reutilización de la celda es por diseño, debido a las restricciones de memoria, pero si tiene una lista con, por ejemplo, 50 elementos, y comienza a establecer marcas de verificación adicionales donde no se desean, esto hace que todo el esfuerzo sea inútil.TableView Reutilización de células y marcas de verificación no deseadas: esto me está matando

Todo lo que quiero hacer es establecer una marca de verificación en una celda que he seleccionado. Lo he intentado utilizando mi propia clase de celda personalizada y las celdas estándar generadas por una placa de caldera clase TableView, pero siempre termina igual.

Apple incluso tiene un proyecto de ejemplo llamado TouchCell que puede descargar desde el centro de desarrollo, que se supone que muestra una forma diferente de establecer una marca de verificación usando una celda personalizada con un control de imagen a la izquierda. El proyecto utiliza un objeto de diccionario para una fuente de datos en lugar de una matriz mutable, por lo que para cada elemento hay un valor de cadena y un valor comprobado bool. Se supone que este valor comprobado bool establece la marca de verificación para que pueda rastrear los elementos seleccionados. Este proyecto de ejemplo también muestra este comportamiento ridículo tan pronto como rellena el TableView con más de 15 celdas. La reutilización de las celdas comienza a establecer marcas de verificación no deseadas.

Incluso he intentado experimentar con el uso de un identificador de celda verdaderamente único para cada celda. Entonces, en lugar de que cada celda tenga algo como @ "Acell" utilicé una int estática, fundida en una cadena para que las células obtuvieran @ "cell1", @ "cell2" etc. Sin embargo, durante la prueba, pude ver que cientos de nuevas células generado durante el desplazamiento, incluso si la tabla solo tenía 30 elementos.

Solucionó el problema de repetición de la marca de verificación, pero sospecho que el uso de la memoria iba demasiado alto.

Parece que las celdas que no están actualmente en el área visible de la tabla se vuelven a crear cuando se vuelven a desplazar a la vista.

¿Alguien ha encontrado una solución elegante a este comportamiento irritante?

Respuesta

17

reutilización celular puede ser difícil pero hay que seguir 2 cosas en mente:

  • Uso uno identificador para uno tipo de celular - El uso de múltiples identificadores en realidad sólo se necesita cuando se utiliza diferente UITableViewCell -subclases en una vista de tabla y debe confiar en su comportamiento diferente para las diferentes celdas
  • La celda que reutiliza puede estar en en cualquier estado, lo que significa que debe volver a configurar cada aspecto de la celda, especialmente checkmars/image s/texto/accessoryViews/accessoryTypes y más

Lo que hay que hacer es crear un dispositivo de almacenamiento para sus estados marca de verificación - una matriz simple que contiene Bools (o NSArray contiene booleano NSNumber objetos respectivamente) debería hacerlo.Entonces, cuando usted tiene que crear/reutilizar un uso de células siguiente lógica:

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    static NSString *reuseIdentifier = @"MyCellType"; 
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier]; 
    if(cell == nil) { 
     /* create cell here */ 
    } 
    // Configure cell now 
    cell.textLabel.text = @"Cell text"; // load from datasource 
    if([[stateArray objectAtIndex:indexPath.row] boolValue]) { 
     cell.accessoryType = UITableViewCellAccessoryCheckmark; 
    } else { 
     cell.accessoryType = UITableViewCellAccessoryNone; 
    } 
    return cell; 
} 

entonces usted tendrá que reaccionar en los grifos:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    [stateArray replaceObjectAtIndex:indexPath.row withObject:[NSNumber numberWithBool:![[stateArray objectAtIndex:indexPath.row] boolValue]]]; 
    [tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
} 

Sólo recuerde utilizar NSMutableArray para su almacén de datos;)

+0

Martin, eche un vistazo a esto: – nick

+0

Gracias por la sugerencia Martin. Lo probaré, aunque parece una variación del código en el proyecto TouchCell del DevCenter (código Apple). Usan una clase de diccionario para almacenar el valor BOOL y el texto de la celda. Funciona bien con solo unas pocas celdas (9 o 10) pero se estropea de la misma manera cuando las celdas se vuelven a usar de 20 a 30 o más ... Por cierto, intenté ejecutar una aplicación de prueba a través de instrumentos el día de hoy, donde No reutilizo las celdas en absoluto y en realidad usé menos memoria que el método preferido. (Si entiendo los instrumentos correctamente!). – nick

+0

no he consultado su código de forma acutual pero es probable que se vean similares porque esta es la forma en que desea ir. tal vez deberías subir tu código a alguna parte y publicar el enlace como comentario aquí –

Cuestiones relacionadas