¿Trucos para mejorar el rendimiento de desplazamiento del iPhone UITableView?

89

Tengo una vista uitable que carga imágenes bastante grandes en cada celda y las alturas de las celdas varían según el tamaño de la imagen. El rendimiento del desplazamiento es decente, pero a veces puede ser desigual.

Encontré estos consejos que encontré en el blog de FieryRobot:

desplazamiento-vidrioso-con-uitableview

desplazamiento-más-vidrioso-con-uitableview

¿Alguien tiene algún consejo para mejorar el rendimiento de desplazamiento de uitableview?

Jonás
fuente
Si necesita almacenar en caché las alturas de las celdas (que pueden ser costosas de calcular y también se usan con frecuencia), le he dado un ejemplo. Úselo solo si es adecuado para su aplicación. stackoverflow.com/questions/1371223/…
Paul de Lange

Respuestas:

156
  1. Almacene en caché la altura de las filas (la vista de tabla puede solicitar esto con frecuencia)
  2. Cree una memoria caché usada menos recientemente para las imágenes usadas en la tabla (e invalide todas las entradas inactivas cuando reciba una advertencia de memoria)
  3. Dibuje todo en las UITableViewCell's, drawRect:si es posible, evite las subvistas a toda costa (o si necesita la funcionalidad de accesibilidad estándar, las vistas de contenido drawRect:)
  4. Haga que su UITableViewCellcapa sea opaca (lo mismo ocurre con la vista de contenido si tiene una)
  5. Utilice la funcionalidad reusableCellIdentifier según lo recomendado por los UITableViewejemplos / documentación
  6. Evite degradados / efectos gráficos complicados que no están precocinados en UIImages
rpetrich
fuente
5
Además, las imágenes descargadas deben reducirse al tamaño de imageView antes de mostrarse en la celda.
Zoltán Matók
4
Me gustaría agregar a esta respuesta una de mis experiencias de los últimos años: tener celdas transparentes probablemente nunca sea la causa de un mal rendimiento de desplazamiento. Tenemos una aplicación con celdas MUY complicadas (más de 20 subvistas) y es transparente para mostrar el fondo. Con las optimizaciones adecuadas, la transparencia no hace ninguna diferencia incluso en un 3GS. En realidad, lo que más ralentizó las cosas fue la carga de plumillas antes de que hubiera suficientes celdas para quitar la cola de la vista de tabla. Si usa subvistas, solo asegúrese de tener jerarquías eficientes y no es necesario que use drawRect.
Accatyyc
@Accatyyc, parece que tengo el mismo problema. Hay un pequeño retraso cuando no hay suficientes celdas para quitar de la cola, cuando se quitan de la cola 3-4 celdas, el desplazamiento es suave. ¿Hay alguna forma de precargar celdas para que haya celdas para retirar y no cargar archivos NIB al desplazarse?
Tiois
@Tiois Seguro que la hay. Debe utilizar la forma anterior de retirar las celdas de la cola (no registre clases / nibs, pero créelos si dequeueCellWithIdentifier: devuelve nil). De esta manera, puede crear un conjunto de celdas antes de que exista la vista de la tabla, por ejemplo, creando 20 de ellas antes. Luego, en lugar de crear nuevos en cellForRowAtIndexPath :, primero los extrae de su propio caché, hasta que esté vacío.
Accatyyc
Estoy usando UICollectionView y tengo el mismo problema. En mi archivo de plumilla de celda personalizado. Estoy usando varias subvistas, incluidas UIwebView y UIImageView dentro de UIstackView vertical. cuando me desplazo por mi lista, las celdas reutilizadas tardan un tiempo considerable en reajustar su tamaño y el desplazamiento parece muy irregular.
Mansuu ....
40
  1. Si está subclasificando UITableViewCell, no use un Nib, escríbalo en código. Es mucho más rápido que cargar archivos Nib.
  2. Si está utilizando imágenes, asegúrese de almacenarlas en caché para no tener que cargar desde el archivo más de una vez para cada una (si tiene la memoria, se sorprendería de cuánto espacio ocupan las imágenes).
  3. Haga opacos tantos elementos como sea posible. Del mismo modo, intente no utilizar imágenes con transparencia.
Rana peluda
fuente
3
no te preocupes ... que eran trolls. ¡gran respuesta!
Steav
79
Los votos negativos se debieron probablemente a que "evitar las puntas" es un mal consejo para mejorar el rendimiento. Si está reutilizando células, las células no se reconstruyen a partir de plumillas cuando se desplaza.
Steven Fisher
6
Las puntas son equivalentes en velocidad, o un poco más rápidas según la investigación de Cocoa with Love. cocoawithlove.com/2010/03/…
MaxGabriel
@Steven Fisher usando Nib puede ser más lento cuando la tabla asigna y desasigna celdas, por ejemplo, durante el desplazamiento rápido.
Sound Blaster
3
El uso de NIB puede ser más lento cuando se está construyendo la celda . Si está utilizando el reciclaje de células, solo hay suficientes células asignadas para llenar la pantalla; digamos, tal vez 10 como máximo. Cuando se desplaza, no se crean celdas. Simplemente se reutilizan , no se desasignan ni se reasignan. Y, por supuesto, no hay ningún costo para deslocalizar. Entonces no, esto no es correcto.
Steven Fisher
34

El desarrollador detrás de Tweetie ha escrito mucho sobre esto y tiene un código que demuestra cómo se hizo para esa aplicación. Básicamente, él / ella aboga por una vista personalizada por celda de tabla y dibujarla manualmente (en lugar de realizar una subvista con Interface Builder, entre otras opciones).

desplazamiento-rápido-en-tweetie-con-uitableview

Además, Apple ha actualizado su propio código de muestra para TableView en sus tutoriales de TableViewSuite (¿tal vez en respuesta a esto?)

TableViewSuite

beno
fuente
1
Esta es una solución asombrosa. Tengo curiosidad por saber cómo agregaría un UIButton en cellView. ¿Se dibuja en el método drawRect?
Sukitha Udugamasooriya
1
@beno, tu enlace parece roto (el primero) ¿Alguna posibilidad de poner nuestras manos en el artículo original?
apouche
3
El artículo original se puede leer aquí: web.archive.org/web/20100922230053/http://blog.atebits.com/2008/…
jverdi
enlace agregado al archivo web ya que la versión original no existe
Ralph Willgoss
1

El asesino de rendimiento # 1 para el desplazamiento de UITableView es dibujar sombras en cualquier capa de vista de celda, por lo que si el rendimiento del desplazamiento es importante, no haga sombras a menos que básicamente no ralentice su hilo principal.

Pensé que esto tenía que decirse, ya que ninguna de las respuestas aceptadas mencionaba sombras y capas. : +)

JackyJohnson
fuente
6
si los problemas son las sombras agregue estas dos líneas de código y todo funcionará perfectamente self.layer.shouldRasterize = YES; self.layer.rasterizationScale = UIScreen.mainScreen.scale;
Pedro Romão
0

Cualquier problema con el UITableViewrendimiento del desplazamiento se puede resolver utilizando técnicas ya descritas en otras respuestas. Sin embargo, muchas veces el rendimiento lento es causado por algo intrínsecamente erróneo o repetitivo.

El hecho de que UITableViewreutilice las celdas y el hecho de que cada celda pueda necesitar su propia imagen, juntos hace que la solución sea un poco compleja. De cómo se está resolviendo de manera general, aquí resumo las cosas que deben ser atendidas:

  1. Cargue datos en la fuente de datos, desde REST / base de datos. Este paso debe realizarse en segundo plano, eventualmente usando dispatch_async junto con la cola de GCD.
  2. Cree e inicialice objetos de modelo de datos relevantes y colóquelos dentro de una matriz
  3. [tableView reloaddata]
  4. En el interior cellForRowAtIndexPath, incluya el código que establecerá los datos (texto) del objeto de modelo de datos correcto de la matriz.
  5. Ahora las imágenes también pueden estar en forma de URL, por lo que este paso puede ser un poco peculiar debido a la reutilización de celdas realizada por la vista de tabla. El meollo del hecho es cargar una vez más la imagen desde la caché del dispositivo / URL usando la cola asíncrona, luego configurarla para corregir la imagen de celda (cualquiera que sea la propiedad de la imagen de su celda).

Para evitar problemas, consulte este tutorial sobre la carga diferida de imágenes dentro de la vista de tabla.

Nirav Bhatt
fuente