En iOS, ¿cuál es la forma más rápida de almacenar en caching una image de pantalla dibujada y mostrarla?

En lugar de dejar que drawRect dibujar miles de puntos cada vez, creo que hay varias forms de "almacenar en caching la image en la pantalla" y cualquier dibujo adicional, agregaremos a esa image y solo mostraremos esa image cuando drawRect momento de drawRect :

  1. Use BitmapContext y dibuje en un bitmap, y en drawRect , dibuje este bitmap.

  2. Use CGLayer y dibuje el CGLayer en drawRect , y esto puede ser más rápido que el método 1, ya que esta image está almacenada en caching en la tarjeta gráfica (y no contará para el uso de RAM para la "advertencia de memory" en iOS).

  3. Dibuje en una image CGImage y use la capa de la vista: view.layer.contents = (id) cgimage;

Entonces, parece haber tres methods, y creo que CALayer en el método (3) solo puede usar una CGImage para lograrlo. CALayer por sí mismo no puede almacenar en caching una image de pantalla, no como CGLayer en (2).

¿El método (2) es el más rápido de los tres, y existen otros methods que pueden lograr esto? De hecho, planeo animar algunas imágenes de pantalla, (haciendo más de 5 o 6), e intentaré usar CADisplayLink para probar una tasa de cuadros más alta de 60 fps. ¿Algún método (1), (2) o (3) utilizará la memory en la tarjeta gráfica y, por lo tanto, no utilizará la RAM y, por lo tanto, es less probable que reciba una advertencia de memory de iOS también?

Según las últimas preguntas que has preguntado, parece que estás confundiendo completamente a CGLayers y CALayers. Son conceptos diferentes y no están realmente relacionados entre sí. Un CGLayer es una construcción Core Graphics que ayuda en la representación repetida del contenido dentro del canvas de un context Core Graphics, y se confina dentro de una única vista, bitmap o context PDF. Rara vez he tenido la necesidad de trabajar con un CGLayer.

Un CALayer es una capa Core Animation, y hay un respaldo cada UIView dentro de iOS (y NSViews respaldado por capas en la Mac). Se ocupa de estos todo el time en iOS, porque son una pieza fundamental de la architecture de la interfaz de usuario. Cada UIView es efectivamente un envoltorio liviano alnetworkingedor de un CALayer, y cada CALayer a su vez es efectivamente un envoltorio alnetworkingedor de un quad texturado en la GPU.

Cuando se visualiza una UIView en pantalla, la primera vez que se debe representar el contenido (o cuando se desencadena un nuevo dibujo) Core Graphics se usa para tomar sus líneas, arcos y otro dibujo vectorial (a veces también incluye maps de bits rasterizados) y rasterizar ellos a un bitmap. Este bitmap se carga y almacena en caching en la GPU a través de su CALayer.

Para los cambios en la interfaz, como vistas movidas, giradas, escaladas, etc., estas vistas o capas no necesitan volver a dibujarse, lo que es un process costoso. En cambio, solo se transforman en la GPU y se comstackn en su nueva location. Esto es lo que permite la animation suave y el desplazamiento visto a través de la interfaz de iOS.

Por lo tanto, querrá evitar usar Core Graphics para volver a dibujar algo si desea tener el mejor performance. Caché qué partes de la escena puedes dentro de CALayers o UIViews. Piense en cómo la animation de estilo más antiguo usó celdas para contener partes de la escena que moverían, en lugar de que los animadores networkingibujaran cada cambio en la escena.

Puedes fácilmente get cientos de CALayers para animar sobre la pantalla sin problemas en dispositivos iOS modernos. Sin embargo, si quiere hacer miles de puntos para algo así como un sistema de partículas, será mejor que se lo sirva moviéndose a OpenGL ES para eso y renderizado usando GL_POINTS. Eso requerirá mucho más código para configurar, pero puede ser la única manera de get un performance aceptable para los "miles de puntos" sobre los que pregunta.

Un método rápido que permite tanto el almacenamiento en caching de charts como la modificación de los contenidos de charts almacenados en caching es una mezcla de sus methods (1) y (3).

(1) Cree su propio context gráfico respaldado por bitmap, dibuje sobre él y luego modifíquelo en cualquier momento (agregue de forma incremental un punto o miles de puntos de vez en cuando, etc.) según sea necesario. Lamentablemente, será invisible, porque no hay forma de get directamente ningún bitmap en la pantalla en un dispositivo iOS.

Entonces, además,

(3) a una velocidad de fotogtwigs (60 Hz, 30 Hz, etc.), si el bitmap está sucio (se ha modificado), convierta el context de bitmap en una image CG y asigne esa image al contenido de una CALayer. Eso convertirá y copyrá la memory de su bitmap integer en el caching de textura de la GPU (esta es la parte lenta). Luego usa la animation central para hacer lo que quieras con la capa (enjuáguese, compárala, vuélvela por la window, etc.) para mostrar la textura hecha a partir de tu bitmap. Entre bastidores, la animation Core eventualmente permitirá que la GPU lance un cuádruple usando esa textura en algunos mosaicos de windows compuestos que eventualmente se enviarán a la pantalla de los dispositivos (esta descripción probablemente omite un montón de etapas en los charts y las tuberías de la GPU). Enjuague y repita según sea necesario en el bucle de ejecución principal de la IU. Mi publicación de blog en este método está aquí .

No hay forma de modificar parcialmente el contenido de una textura de GPU existente en uso. Usted tiene que replacelo con una nueva carga de textura completa o una capa compuesta en la parte superior de la capa de la textura. Así, terminarás manteniendo el doble de la memory en uso, algunos en el espacio de direcciones de las CPU, algunos en el caching de textura de la GPU.