que iphone ios objective-c ipad uiscrollview
here

iphone - que - ¿Qué es un FPS aceptable para el desplazamiento y cuáles son los consejos para mejorar el rendimiento?



wkwebview ios (8)

Veo en muchos videos de la WWDC que dicen que quieres alcanzar los 60.0 FPS lo más cerca posible para obtener una mejor experiencia de desplazamiento sin problemas. Tengo un UIScrolLView que carga una imagen y un par de vistas de tabla a la vez. Actualmente estoy recibiendo 30 FPS. Esto es la mitad de lo que recomienda el FPS. Solo me pregunto qué FPS suelen obtener para una vista de tabla / desplazamiento que carga imágenes y otras cosas pesadas / cosas de renderizado.

¿Algún otro consejo para optimizar FPS? He pasado la última semana hasta ahora activando Instrumentos usando el generador de perfiles de tiempo, las asignaciones y la herramienta de animación principal para optimizar todo lo que pueda.

Solo para aclarar un poco lo que tengo. Tengo un diseño estilo albañilería / cascada / pinterest en el iPad. Así que no es solo un UITableView regular. Es un UIScrollView que llena toda la pantalla y está lleno de un par de UIView. Cada una de esta vista tiene un UIImageView 150x150 y un UITableView y también tiene alguna etiqueta atribuida, dibujada usando Core Text. Por lo tanto, cuando ve la pantalla, puede ver 5-8 vistas de tabla de una sola vez, cada celda nuevamente tiene un UIImageView y luego cada celda representa una etiqueta atribuida dibujada usando el texto central.

Así que puedes imaginar cuán profundo y complicado es esto. Esta no es solo una vista de tabla regular con un UIImageView. Sé cómo obtener 60 FPS con un solo UITableView en un iPhone con un UIImage. El concepto es cargar imágenes de forma asíncrona y no bloquear el hilo principal tanto como sea posible.

EDITAR:

Parece que el problema aquí es el UITableView que tengo dentro de mi vista ... cuando lo elimino de UIView, tengo un desplazamiento muy suave ...

Subí un proyecto de muestra que es una versión más simple de lo que tengo, pero muestra claramente el problema. El enlace esta here



Hay algunas cosas que puede hacer en general para obtener un mejor rendimiento de la vista de tabla:

1) Cambie al método de Loren Brichter para dibujar UITableViewCell''s (por falta de un mejor enlace: http://www.therefinedgeek.com.au/index.php/2010/12/21/fast-scrolling-uitableview-updates-for-ios-4-2/ )

Básicamente, todo lo que hace su código es procesar todo el contenido de su celda como una UIView opaca, que UITableView (y CoreGraphics) puede explotar rápidamente en un UITableViewCell

Si no desea hacer todo el diseño de su celda en drawRect :, aún puede usar nibs, pero:

  • Asegúrate de que cada subvista esté marcada como opaca
  • No tengo subvistas transparentes / semitransparentes
  • ¡No tengo ninguna imagen con un canal alfa! = 1.0f.

2) No permita que UIImageView realice ninguna escala para mostrar su imagen, déle un UIImage del tamaño correcto

3) Si está utilizando iOS 5 y superior, puede registrar una punta para un identificador de celda en particular. De esa manera, cuando llama a [tableView dequeueReusableCellWithIdentifier:], tiene la garantía de obtener una celda. La asignación de celdas es más rápida (según Apple), y puedes escribir menos código:

- (void)viewDidLoad { UINib *nib = [UINib nibWithNibName:@"MyCell" bundle:nil]; [self.tableView registerNib:nib forCellReuseIdentifier:@"MyCellIdentifier"]; } // ... - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *cellIdentifier = @"MyCellIdentifier"; MyCell *cell = (MyCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier]; // Commented out code is no longer needed //if (cell == nil) { // cell = [[MyCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier]; //} // setup cell return cell; }

4) Visualización de imágenes descargadas de la web.

  • Mostrar una imagen predeterminada (algo que ver mientras se descarga la imagen real)
  • Inicie la descarga en un hilo separado (pista: use dispatch_async () de GCD)
  • Cuando aparezca la imagen, guárdela (sugerencia: NSCache) y muéstrela en la celda.
    • Realice todas las descargas de imágenes / almacenamiento en caché fuera del hilo principal; lo único que debe hacer en el hilo principal es configurar la imagen (recuerde que el código de UI TIENE que estar en el hilo principal)

Probablemente querrá escribir un UIImageView compatible con async (o usar una biblioteca existente).

Manténgase alejado de EGOImageView, aunque tiene una descarga asíncrona, realiza una búsqueda de caché (que está en el disco, lo que significa un IO de disco costoso) en el hilo principal antes de enviarlo a un hilo de fondo para la descarga. Solía ​​usarlo, pero terminé escribiendo mi propio conjunto de clases para manejar esto, y es significativamente más rápido.

-

Solo sigue estos, y otras cosas que otras personas han escrito aquí, y tendrás vistas de tabla que se desplazarán como un cristal en ningún momento :)


Lo que he hecho es usar NSCache. He creado una clase pequeña con propiedades que se ajustan al protocolo de datos de NSCache (es realmente fácil de hacer). Entonces, lo que hago es crear una relación entre cada celda en la tabla principal y varias cosas que vale la pena almacenar en caché: cadenas NSAttributed, imágenes, etc., realmente todo lo que requiere trabajo para crear. No lo precargo pero tu podrías.

Cuando la vista de tabla le solicite que proporcione una celda, busque en su caché su objeto principal. Si está allí, tira todos los objetos que necesites. Si la memoria caché no tiene el objeto, entonces obtenga los datos a la manera antigua, pero antes de terminar, guárdelos también en la memoria caché.

Esto realmente me ayudó a reducir el "tartamudeo" al desplazarme por la celda. Además, NO animes nada en la celda, eso mata el rendimiento. Todo debe estar completamente rendido.

Otra cosa para recordar: asegúrese de que la vista que se puede configurar como opaca tenga su propiedad establecida en SÍ. Eso ayuda al sistema a renderizar la celda (incluida la vista de fondo si utiliza una).

EDITAR:

Por lo que proporcionó información que incluía UITableViews puede ser el problema raíz. Así que dos sugerencias:

1) ¿Puedes dar un paso atrás y descubrir cómo hacer que el scrollView sea un solo UITableView? Con encabezados de tabla y pies de página, y encabezados de sección y pies de página, e incluso la capacidad de hacer que una celda sea una vista flotante, ¿no puede descubrir cómo hacer una búsqueda de arquitecto de lo que tiene?

2) Así que decides no a la sugerencia 1. Luego, haz esto. Piense en el espacio utilizado por la vista de tabla como una vista de contenedor. Cuando se edite la vista de tabla, tome una instantánea de la imagen y mantenga esta imagen alrededor. Tan pronto como el usuario comience a desplazarse, cambie la vista de tabla por las imágenes. Cuando el scrollView se detiene, vuelve a intercambiar el UITableView. Esto, por supuesto, requerirá algunos ajustes finos. De hecho, probablemente podría superponer una instantánea de imagen opaca sobre la mesa (lo que la ocultará y evitará que se le pida dibujar) durante el desplazamiento.


Me UITableViewController a 60 fps con mi UITableViewController donde la tabla contiene aproximadamente 2000 celdas y cada celda saca una imagen de la web. El truco es cargar las imágenes de forma perezosa a medida que las necesite. Este código de ejemplo de Apple es bastante útil.

La idea general es mantener la interfaz de usuario receptiva al no bloquear el hilo principal. Realiza descargas y otras tareas que consumen mucho tiempo en otro hilo.


Muchas cosas afectan el rendimiento del render, aquí hay algunos elementos que puede verificar:

  • Perfil - ¡Dijiste que ya hiciste esto, gran trabajo! Desafortunadamente, el perfil se suele pasar por alto, aunque puede revelar problemas inesperados. En una aplicación estaba trabajando en un calendario con diferentes celdas que representan fechas. Al principio se desplaza lentamente entre celdas, lo que fue inesperado. Pensé que tal vez estaba dibujando unas cuantas celdas demasiadas. Después de hacer un perfil, descubrí que [NSCalender currentCalender] estaba usando el 85% de mi tiempo de CPU. Después de arreglar eso, todo se desplazó genial!

  • Imágenes - Las imágenes grandes ponen mucha carga en CoreGraphics. El desplazamiento en particular requiere muchas operaciones de dibujo para moverlos. Un consejo es escalar las imágenes en el dispositivo lo menos posible, lo que hace que el trabajo de CoreGraphics sea mucho más fácil. Si una imagen es dos veces más grande que la vista que la muestra, cambie el tamaño del UIImage antes de mostrarla en la vista. Los dispositivos iOS manejan mejor los PNG. Están comprimidos por una herramienta (pngcrush) en tiempo de compilación e iOS tiene un hardware especial para renderizarlos.

Edición : JPGs son probablemente una mejor opción para las fotos. Los dispositivos iOS también tienen decodificadores JPG dedicados.

  • Dibujo personalizado: si es posible, reduzca la cantidad de dibujo CGContext personalizado que realiza. Muchos dibujos personalizados tienen efectos negativos en la velocidad de animación. Me gustaría considerar el uso de una imagen sobre un dibujo personalizado complejo, si es posible.

  • Cull - Sólo dibuja las cosas que necesitas. UITableView descarga y carga las celdas automáticamente a medida que aparecen, por lo que esto se hace por usted, pero cualquier dibujo personalizado de CGContext solo debe hacerse cuando esa parte esté visible. También las sombras de vista automáticas pueden ser muy lentas en mi experiencia.

  • Reutilización: use el identificador de reutilización en UITableView , esto permitirá que UITableView reutilice los objetos de celda en lugar de reasignarlos a medida que se desplaza; observe la respuesta a esta question . También reutilice UIImages lugar de asignar múltiples para el mismo archivo. imageNamed almacena imágenes en caché automáticamente, pero imageFromContents del archivo no lo hace.

  • Cree el suyo propio: puede crear su propia clase de vista de cuadrícula que elimina las vistas de subvistas ocultas en la pantalla y se desplaza con la carga perezosa de contenido. Al escribir una solución personalizada, puede controlar completamente el proceso y crear un diseño optimizado para el contexto de uso. Para la mayoría de los casos de uso, le será difícil construir algo mejor que el estándar de Apple, pero lo he visto en casos específicos.

  • Último recurso: reduzca el tamaño de la vista ofensiva (mejora el filtrado), divida el contenido en varias páginas, reduzca el tamaño de las imágenes, elimine los dispositivos más antiguos que no funcionan tan bien. Me conformaría con 30 FPS antes de sacrificar la mayoría de esas cosas. Los dispositivos continuarán haciéndose más rápidos, los dispositivos más antiguos serán eliminados y su aplicación gradualmente se volverá más rápida.


Quieres 60 fps, pero 30 fps no parece demasiado terrible en la actualidad. Pero trataría de lograr 60 fps para una apariencia más suave mientras me desplazo.

Hay muchas posibilidades de mejora del rendimiento, que también se muestran en varios tutoriales


Si bien 60 FPS es lo ideal, juegos como Halo se ejecutan de manera muy atractiva en 30 FPS. El caos del campo de batalla en Halo probablemente involucre un movimiento más sorprendente y rápido que la mayoría de las listas, ¡incluso las más complejas como la suya!


el ojo humano ve a unos 60 FPS, por eso es recomendable, pero 30 FPS también aparecerán muy suaves, especialmente cuando un usuario regular lo está viendo, en lugar de que intentes encontrar la mayor cantidad posible de arreglos. Obviamente, esto depende de qué tan rápido vaya el desplazamiento, si la diferencia de un cuadro a otro es un movimiento de unos pocos píxeles, 30 FPS funcionarán bien, pero un movimiento más rápido requerirá un FPS más alto para que aparezca suave