Para aclarar el propósito de esta pregunta: Sé CÓMO crear vistas complicadas con ambas subvistas y usando drawRect. Estoy tratando de entender completamente cuándo y por qué usar uno sobre el otro.
También entiendo que no tiene sentido optimizar tanto antes de tiempo, y hacer algo de la manera más difícil antes de hacer un perfil. Considere que me siento cómodo con ambos métodos, y ahora realmente quiero una comprensión más profunda.
Gran parte de mi confusión proviene de aprender a hacer que el rendimiento de desplazamiento de la vista de tabla sea realmente suave y rápido. Por supuesto, la fuente original de este método es del autor detrás de twitter para iPhone (anteriormente tweetie). Básicamente dice que para hacer que el desplazamiento de la tabla sea suave, el secreto es NO usar subvistas, sino hacer todo el dibujo en una vista personalizada. Básicamente, parece que el uso de muchas subvistas ralentiza el procesamiento porque tienen mucha sobrecarga y se vuelven a componer constantemente sobre sus vistas principales.
Para ser justos, esto se escribió cuando el 3GS era bastante nuevo, e iDevices se ha vuelto mucho más rápido desde entonces. Aún así, este método se sugiere regularmente en las páginas web y en otros lugares para tablas de alto rendimiento. De hecho, es un método sugerido en el Código de muestra de tabla de Apple , se ha sugerido en varios videos de WWDC ( Dibujo práctico para desarrolladores de iOS ) y en muchos libros de programación de iOS .
Incluso hay herramientas increíbles para diseñar gráficos y generar código de Core Graphics para ellos.
Así que al principio me hacen creer "hay una razón por la que existe Core Graphics. ¡Es RÁPIDO!"
Pero tan pronto como creo que tengo la idea de "Favorecer Core Graphics cuando sea posible", empiezo a ver que drawRect a menudo es responsable de la poca capacidad de respuesta en una aplicación, es extremadamente costosa en cuanto a memoria y realmente grava la CPU. Básicamente, que debería " Evitar anular drawRect " (WWDC 2012 iOS App Performance: Graphics and Animations )
Así que supongo que, como todo, es complicado. ¿Tal vez puedan ayudarme a mí mismo y a otros a comprender cuándo y por qué usar drawRect?
Veo un par de situaciones obvias para usar Core Graphics:
- Tienes datos dinámicos (ejemplo del gráfico de acciones de Apple)
- Tiene un elemento de interfaz de usuario flexible que no se puede ejecutar con una simple imagen de tamaño variable
- Está creando un gráfico dinámico, que una vez renderizado se usa en varios lugares
Veo situaciones para evitar Core Graphics:
- Las propiedades de su vista deben ser animadas por separado
- Tiene una jerarquía de visualización relativamente pequeña, por lo que no vale la pena ganar ningún esfuerzo adicional percibido con CG
- Desea actualizar partes de la vista sin volver a dibujar todo
- El diseño de sus subvistas necesita actualizarse cuando cambia el tamaño de la vista principal
Así que otorga tu conocimiento. ¿En qué situaciones recurres a drawRect / Core Graphics (que también podría lograrse con subvistas)? ¿Qué factores te llevan a esa decisión? ¿Cómo / por qué se recomienda dibujar en una vista personalizada para el desplazamiento suave de las celdas de la tabla? ¿Qué pasa con las imágenes de fondo simples (cuando las creas con CG vs usando una imagen PNG redimensionable)?
Es posible que no se necesite una comprensión profunda de este tema para crear aplicaciones que valgan la pena, pero no me encanta elegir entre técnicas sin poder explicar por qué. Mi cerebro se enoja conmigo.
Actualización de preguntas
Gracias a todos por la información. Algunas preguntas aclaratorias aquí:
- Si está dibujando algo con gráficos básicos, pero puede lograr lo mismo con UIImageViews y un png pre-renderizado, ¿siempre debe seguir esa ruta?
- Una pregunta similar: Especialmente con herramientas rudas como esta , ¿cuándo debería considerar dibujar elementos de interfaz en gráficos básicos? (Probablemente cuando la visualización de su elemento es variable. Por ejemplo, un botón con 20 variaciones de color diferentes. ¿Algún otro caso?)
- Dado mi entendimiento en mi respuesta a continuación, ¿podrían lograrse las mismas ganancias de rendimiento para una celda de tabla capturando efectivamente un mapa de bits de instantánea de su celda después de su renderizado UIView complejo y mostrándolo mientras se desplaza y oculta su vista compleja? Obviamente algunas piezas tendrían que ser resueltas. Solo un pensamiento interesante que tuve.
fuente
Voy a intentar mantener un resumen de lo que estoy extrapolando de las respuestas de otros aquí, y hacer preguntas aclaratorias en una actualización de la pregunta original. Pero animo a otros a que sigan respondiendo y voten por aquellos que han proporcionado buena información.
Enfoque general
Está bastante claro que el enfoque general, como Ben Sandofsky mencionó en su respuesta , debería ser "Siempre que pueda, use UIKit. Realice la implementación más simple que funcione. Perfil. Cuando haya un incentivo, optimice".
El porque
Dibujar el contenido de las celdas en una UIView plana puede mejorar enormemente su FPS en las tablas de desplazamiento.
Como dije anteriormente, la CPU y la GPU son dos posibles cuellos de botella. Como generalmente manejan cosas diferentes, debe prestar atención a qué cuello de botella se está enfrentando. En el caso de las tablas de desplazamiento, no es que Core Graphics esté dibujando más rápido, y es por eso que puede mejorar enormemente su FPS.
De hecho, Core Graphics puede ser más lento que una jerarquía UIView anidada para el renderizado inicial. Sin embargo, parece que la razón típica para el desplazamiento entrecortado es que está obstruyendo la GPU, por lo que debe abordar eso.
Por qué anular drawRect (usando gráficos centrales) puede ayudar al desplazamiento de la tabla:
Por lo que entiendo, la GPU no es responsable de la representación inicial de las vistas, sino que recibe texturas o mapas de bits, a veces con algunas propiedades de capa, después de que se hayan renderizado. Luego es responsable de componer los mapas de bits, renderizar todos los efectos de capa y la mayoría de la animación (Core Animation).
En el caso de las celdas de vista de tabla, la GPU se puede embotellar con jerarquías de vista complejas, porque en lugar de animar un mapa de bits, está animando la vista principal y haciendo cálculos de diseño de subvista, renderizando efectos de capa y componiendo todas las subvistas. Entonces, en lugar de animar un mapa de bits, es responsable de la relación de un montón de mapas de bits y cómo interactúan, para la misma área de píxeles.
En resumen, la razón por la que dibujar su celda en una vista con gráficos principales puede acelerar el desplazamiento de su tabla NO es porque esté dibujando más rápido, sino porque está reduciendo la carga en la GPU, que es el cuello de botella que le da problemas en ese escenario particular .
fuente
Soy un desarrollador de juegos, y estaba haciendo las mismas preguntas cuando mi amigo me dijo que mi jerarquía de vistas basada en UIImageView iba a ralentizar mi juego y hacerlo terrible. Luego procedí a investigar todo lo que pude encontrar sobre si usar UIViews, CoreGraphics, OpenGL o algo de terceros como Cocos2D. La respuesta constante que recibí de amigos, maestros e ingenieros de Apple en WWDC fue que al final no habrá mucha diferencia porque en algún nivel todos están haciendo lo mismo . Las opciones de nivel superior como UIViews se basan en las opciones de nivel inferior como CoreGraphics y OpenGL, solo están envueltas en código para que sea más fácil de usar.
No use CoreGraphics si solo va a terminar reescribiendo la UIView. Sin embargo, puede ganar algo de velocidad al usar CoreGraphics, siempre que haga todo su dibujo en una vista, pero ¿realmente vale la pena ? La respuesta que he encontrado es generalmente no. Cuando comencé mi juego, estaba trabajando con el iPhone 3G. A medida que mi juego creció en complejidad, comencé a ver cierto retraso, pero con los dispositivos más nuevos era completamente imperceptible. Ahora tengo mucha acción y el único retraso parece ser una caída de 1-3 fps cuando se juega en el nivel más complejo en un iPhone 4.
Aún así, decidí usar los instrumentos para encontrar las funciones que ocupaban más tiempo. Descubrí que los problemas no estaban relacionados con mi uso de UIViews . En cambio, repetidamente estaba llamando a CGRectMake para ciertos cálculos de detección de colisión y cargando archivos de imagen y audio por separado para ciertas clases que usan las mismas imágenes, en lugar de hacer que extraigan de una clase de almacenamiento central.
Entonces, al final, es posible que pueda lograr una ligera ganancia al usar CoreGraphics, pero por lo general no valdrá la pena o puede que no tenga ningún efecto. La única vez que uso CoreGraphics es cuando dibujo formas geométricas en lugar de texto e imágenes.
fuente