Red de conocimiento informático - Conocimiento informático - Cómo escribir aplicaciones móviles iOS estables y fluidas

Cómo escribir aplicaciones móviles iOS estables y fluidas

Destrucción de objetos

Aunque la destrucción de objetos no consume muchos recursos, no se puede ignorar la acumulación. Por lo general, cuando una clase de contenedor contiene una gran cantidad de objetos, el consumo de recursos cuando se destruye es muy obvio. De manera similar, si el objeto se puede liberar en el hilo de fondo, muévalo al hilo de fondo. Aquí hay un pequeño consejo: capture el objeto en un bloque, luego tírelo a la cola en segundo plano y envíe un mensaje aleatorio para evitar advertencias del compilador, de modo que el objeto pueda destruirse en el hilo en segundo plano.

NSArray *tmp = self.array;

self.array = nil;

dispatch_async(cola, ^{

[tmp class];

});

Cálculo de diseño

El cálculo de diseño de vista es el lugar más común en la aplicación que consume recursos de CPU. Si el diseño de la vista se puede calcular de antemano en el hilo de fondo y el diseño de la vista se almacena en caché, entonces básicamente no habrá problemas de rendimiento en este lugar.

No importa qué tecnología se utilice para diseñar la vista, al final recaerá en el ajuste de propiedades como UIView.frame/bounds/center. Como se mencionó anteriormente, ajustar estos atributos consume muchos recursos, así que intente calcular el diseño con anticipación y ajuste los atributos correspondientes a la vez cuando sea necesario, en lugar de calcular y ajustar estos atributos varias veces y con frecuencia.

Diseño automático

El diseño automático es una tecnología promovida por la propia Apple. En la mayoría de los casos, también puede mejorar la eficiencia del desarrollo. Sin embargo, el diseño automático a menudo produce serios problemas de rendimiento para vistas complejas. A medida que aumenta la cantidad de vistas, el consumo de CPU causado por el diseño automático aumentará exponencialmente. Si no desea ajustar manualmente propiedades como el marco, puede usar algunos métodos de herramientas (como las propiedades comunes de acceso directo izquierda/derecha/arriba/abajo/ancho/alto) o usar marcos como ComponentKit y AsyncDisplayKit.

Cálculo de texto

Si una interfaz contiene una gran cantidad de texto (como Weibo, WeChat Moments, etc.), el cálculo del ancho y alto del texto ocupará una gran parte. de los recursos y es inevitable. Si no tiene requisitos especiales para la visualización de texto, puede consultar la implementación interna de UILabel: use [NSAttributedStringboundingRectWithSize:options:context:] para calcular el ancho y alto del texto, y use -[NSAttributedString drawWithRect:options:context:] para dibujar el texto. Aunque estos dos métodos funcionan bien, aún deben ejecutarse en un subproceso en segundo plano para evitar bloquear el subproceso principal. Si usa CoreText para dibujar texto, primero puede generar un objeto de composición tipográfica CoreText y luego calcularlo usted mismo, y el objeto CoreText se puede conservar para su uso posterior en el dibujo.

Representación de texto

Todos los controles de contenido de texto que se pueden ver en la pantalla, incluido UIWebView, están tipográficos y dibujados como mapas de bits a través de CoreText en el nivel inferior. La composición tipográfica y el dibujo de controles de texto comunes (UILabel, UITextView, etc.) se realizan en el hilo principal. Cuando se muestra una gran cantidad de texto, la presión sobre la CPU será muy alta. Solo hay una solución para esto, que es personalizar el control de texto y usar TextKit o CoreText de nivel más bajo para dibujar el texto de forma asincrónica. Aunque esto es muy problemático de implementar, las ventajas que aporta también son muy grandes. Una vez creado el objeto CoreText, puede obtener directamente el ancho y alto del texto y otra información, evitando múltiples cálculos (un cálculo al ajustar el tamaño de UILabel). , y otro cálculo interno cuando se dibuja UILabel). Cuéntelo una vez; los objetos CoreText ocupan menos memoria y se pueden almacenar en caché para múltiples renderizaciones más adelante.

Decodificación de imágenes

Cuando crea una imagen utilizando los métodos de UIImage o CGImageSource, los datos de la imagen no se decodifican inmediatamente. La imagen está configurada en UIImageView o CALayer.contents, y los datos en CGImage no se decodificarán hasta que CALayer se envíe a la GPU. Este paso ocurre en el hilo principal y es inevitable. Si desea evitar este mecanismo, un enfoque común es dibujar primero la imagen en CGBitmapContext en el hilo de fondo y luego crear la imagen directamente desde el mapa de bits. Actualmente, las fototecas online más comunes vienen con esta función.

Dibujo de imágenes

El dibujo de imágenes generalmente se refiere al proceso de dibujar imágenes en el lienzo usando métodos que comienzan con CG y luego crear imágenes a partir del lienzo y mostrarlas. El lugar más común para esto es dentro de [UIView drawRect:]. Dado que los métodos CoreGraphic generalmente son seguros para subprocesos, el dibujo de imágenes se puede realizar fácilmente en un subproceso en segundo plano. Un proceso de dibujo asincrónico simple es aproximadamente el siguiente (la situación real será mucho más complicada que esta, pero el principio es básicamente el mismo):

- (void)display {

despacho_async(backgroundQueue, ^{

CGContextRef ctx = CGBitmapContextCreate(...);

// dibujar en contexto...

CGImageRef img = CGBitmapContextCreateImage( ctx);

CFRelease(ctx);

despacho_async(mainQueue, ^{

capa.contents = img;

}) ;

});

}

Causas y soluciones del consumo de recursos de la GPU

En comparación con la CPU, la GPU puede hacer un trabajo relativamente Algo simple: reciba las descripciones de texturas y vértices (triángulos) enviadas, aplique transformaciones, combine y renderice, luego envíelas a la pantalla. Por lo general, el contenido que puede ver son principalmente texturas (imágenes) y formas (gráficos vectoriales de simulación de triángulos).

Representación de texturas

Todos los mapas de bits, incluidas imágenes, texto y contenido rasterizado, eventualmente se enviarán desde la memoria a la memoria de video y se vincularán a la textura de GPU. Ya sea el proceso de envío a la memoria de video o el proceso de ajuste de la GPU y renderizado de textura, se consumen muchos recursos de la GPU. Cuando se muestra una gran cantidad de imágenes en un corto período de tiempo (por ejemplo, cuando TableView tiene muchas imágenes y diapositivas rápidamente), el uso de la CPU es muy bajo, el uso de la GPU es muy alto y la interfaz seguirá funcionando. soltar fotogramas. La única forma de evitar esta situación es minimizar la visualización de una gran cantidad de imágenes en un corto período de tiempo y combinar varias imágenes en una para mostrar la mayor cantidad posible.

Cuando la imagen es demasiado grande y excede el tamaño de textura máximo de la GPU, la imagen debe ser preprocesada por la CPU primero, lo que consume recursos adicionales tanto para la CPU como para la GPU. Actualmente, el límite superior de tamaño de textura para iPhone 4S y superiores es 4096x4096, así que trate de no permitir que el tamaño de las imágenes y vistas exceda este valor.

Mezcla de vistas (composición)

Cuando se superponen y muestran varias vistas (o CALayer), la GPU primero las mezclará. Si la estructura de la vista es demasiado compleja, el proceso de combinación también consumirá muchos recursos de GPU. Para mitigar la sobrecarga de GPU de esta situación, las aplicaciones deben minimizar el número y la jerarquía de vistas y marcar las vistas opacas con el atributo opaco para evitar una composición inútil de canales alfa.

Por supuesto, también puede utilizar el método anterior para renderizar previamente varias vistas en una imagen para su visualización.

Generación de gráficos

Los bordes, redondeos, sombras, máscaras y la visualización de gráficos vectoriales de CALayer generalmente activan la representación fuera de la pantalla, y la representación fuera de la pantalla generalmente ocurre en la GPU. Cuando aparece una gran cantidad de CALayer con esquinas redondeadas en una vista de lista y se desliza rápidamente, se puede observar que los recursos de la GPU están completamente ocupados, mientras que los recursos de la CPU se consumen muy poco. En este momento, la interfaz aún puede deslizarse normalmente, pero el número promedio de fotogramas caerá a un nivel muy bajo. Para evitar esta situación, puede intentar activar la propiedad CALayer.shouldRasterize, pero esto transferirá la operación de renderizado fuera de la pantalla original a la CPU. En algunas ocasiones en las que solo se requieren esquinas redondeadas, también puede superponer una imagen de esquinas redondeadas ya dibujada encima de la vista original para simular el mismo efecto visual. La solución más completa es dibujar los gráficos que deben mostrarse como imágenes en el hilo de fondo y evitar el uso de atributos como esquinas redondeadas, sombras y máscaras.