2010-08-23 9 views
32

Cuando Apple desarrolló el UITableView para el primer iPhone, tuvo un problema de rendimiento al desplazarse por él. Entonces, un ingenioso ingeniero descubrió que la causa de esto era que la asignación de objetos tenía un precio, por lo que se le ocurrió una forma de reutilizar las células.UITableView dequeueReusableCellWithIdentifier Theory

"asignación de objeto tiene un costo de rendimiento, especialmente si la asignación tiene que ocurrir repetidamente en un corto período de, digamos, cuando los rollos usuario una vista de tabla. Si se reutilizan las células en lugar de asignar nuevos, usted mejorar en gran medida el rendimiento de la vista de tabla ".

Fuente: Biblioteca de Referencia iOS

volver a utilizar un celular que utilice:

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 

Ahora, lo que me pregunto es, lo que realmente sucede aquí? ¿Se ve en TableView si hay una celda con ese identificador y simplemente devuelve ese? Bueno, sí, pero si envía una referencia en lugar de asignar y tengo una vista de tabla con, digamos, 4 celdas con el mismo identificador, todo visible. ¿Cómo puede multiplicarse en cuatro instancias sin asignar?

Quiero saber esto porque estoy creando un componente de tipo calendario y todas las celdas tienen la misma estructura que el texto dentro de los cambios. Entonces, si pudiera volver a usar mis celdas de alguna manera en lugar de asignar, creo que podría obtener un mejor rendimiento.

Mi propia teoría es que asigna las cuatro celdas (simplemente porque también tiene). Cuando una celda desaparece de la pantalla, se colocará en la cola de reutilización TableView. Cuando se necesita una nueva celda, busca en el que si está disponible una celda con el mismo identificador, invoca el método prepareForReuse en esa celda y se elimina de la cola.

+0

Respuesta corta: Sí. Tiene una cola/conjunto de reutilización diferente que no es lo mismo que las cosas que ya están en la tabla. –

Respuesta

43

dequeueReusableCellWithIdentifier: solo devuelve un cell si se ha marcado como listo para volver a usarse. Es por esto que en casi todos los cellForRowAtIndexPath: método que se verá algo como

 


UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 

if (nil == cell) { 
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault 
            reuseIdentifier:CellIdentifier]; 
} 

// Do something to cell 

return cell; 
 

En efecto, suficientes filas serán destinados a cubrir la parte visible de la tableview (más uno o dos más). Como cells scroll fuera de pantalla, se eliminan del table y se marcan como listos para reuse. A medida que la cola de "celdas disponibles" crece, su línea que solicita un dequeued cell comenzará a obtener un cell para usar, en ese punto ya no tendrá que asignar más.

+3

La parte 'uno o dos más' no es correcta. Asignó * exactamente * lo que se necesita. Pruébalo y verás. –

+0

De hecho, como St3fan dice que si NSLog el método donde solicita una celda, verá que solo solicita la celda que se necesita. – Mark

+2

Tal vez fui un poco apresurado en la forma en que lo expliqué. "Lo que se necesita" varía según la circunstancia. A medida que comienzas a desplazar UITableView, entran en juego más factores. Un ejemplo: si desplaza rápidamente una vista de tabla larga, es posible hacer que la tabla solicite una celda cuando no hay ninguna disponible para la eliminación de la cola. –

13

El código para deqeueueReusableCellsWithIdentifier: se verá algo como esto:

(Tomado de uno de mis propios proyectos en los que hacer algo similar con vistas/páginas en una vista de desplazamiento paginado)

- (UIView*) dequeueReusablePage 
{ 
    UIView* page = [reusablePages_ anyObject]; 
    if (page != nil) { 
     [[page retain] autorelease]; 
     [reusablePages_ removeObject: page]; 
    } 
    return page; 
} 

Por lo tanto, mantiene un simple NSMutableSet con objetos reutilizables.

Cuando las celdas se desplazan fuera de la pantalla y ya no son visibles, se ponen en este conjunto.

Así que empiezas con un conjunto vacío y el conjunto solo crecerá si en realidad tienes más datos para mostrar que luego están visibles en la pantalla.

La celda utilizada se desplaza fuera de la parte superior de la pantalla, se coloca en el conjunto y luego se toma para la celda que aparece en la parte inferior de la pantalla.

2

El propósito de dequeueReusableCellWithIdentifier es utilizar menos memoria. si utilizamos 100 celdas en un tableView, entonces necesitamos crear 100 celdas cada vez. Reduce la funcionalidad de la aplicación y puede causar un bloqueo. Para que dequeueReusableCellWithIdentifier inicialice el número particular de celdas que creamos y las celdas se usarán nuevamente para un procesamiento posterior.

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    static NSString *TableIdentifier = @"YourCellIdentifier"; 

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:TableIdentifier]; 

    if (cell == nil) { 
     cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:TableIdentifier]; 
    } 

    ExternalClassTableViewCell *myCell = [[ExternalClassTableViewCell alloc]init]; 
    myCell.MyCellText.text = [tableData objectAtIndex:indexPath.row]; 
    myCell.MyCellImage.backgroundColor = [UIColor blueColor]; 

    return cell; 
} 
Cuestiones relacionadas