Diferencia entre y ?

Quiero cargar algunas imágenes en mi aplicación desde el sistema de archivos. Hay 2 formas sencillas de hacer esto:

[UIImage imageNamed:fullFileName] 

o:

 NSString *fileLocation = [[NSBundle mainBundle] pathForResource:fileName ofType:extension]; NSData *imageData = [NSData dataWithContentsOfFile:fileLocation]; [UIImage imageWithData:imageData]; 

Prefiero el primero porque es mucho menos código, pero he visto a algunas personas decir que la imagen está en caché y que este método usa más memoria. Ya que no confío en la gente en la mayoría de los otros foros, pensé que haría la pregunta aquí, ¿hay alguna diferencia práctica, y si es así, cuál es “mejor”?

Intenté perfilar mi aplicación utilizando el instrumento Object Allocation, y no veo ninguna diferencia práctica, aunque solo he intentado en el simulador, y no en un iPhone.

Depende de lo que estés haciendo con la imagen. El método imageNamed: almacena en caché la imagen, pero en muchos casos eso ayudará con el uso de la memoria. Por ejemplo, si carga una imagen 10 veces para mostrarla junto con algo de texto en una vista de tabla, UIImage solo conservará una única representación de esa imagen en la memoria en lugar de asignar 10 objetos separados. Por otro lado, si tiene una imagen muy grande y no la está reutilizando, es posible que desee cargar la imagen desde un objeto de datos para asegurarse de que se elimine de la memoria cuando haya terminado.

Si no tienes imágenes enormes, no me preocuparía. A menos que vea un problema (y felicitaciones por comprobar la Asignación de Objetos en lugar de la optimización preventiva), elegiría menos líneas de código que las mejoras de memoria insignificantes.

En mi experiencia [UIImage imageNamed:] tiene un rendimiento dramáticamente mejor, especialmente cuando se usa en UITableViews .

No es solo la memoria sino también la deencoding de la image . Tenerlo en caché es mucho más rápido.

Como dice la referencia API de UIImage :

+ (UIImage *) imageNamed: (NSString *) nombre

Este método busca en el caché del sistema un objeto de imagen con el nombre especificado y lo devuelve si existe. Si un objeto de imagen coincidente no está ya en la memoria caché, este método carga los datos de imagen del archivo especificado, lo almacena en la memoria caché y luego devuelve el objeto resultante.

+ (UIImage *) imageWithContentsOfFile: (NSString *) ruta

Este método no almacena en caché el objeto de imagen.

entonces, podemos ver que si tiene muchos elementos de UI (como UITableViewCell) que pueden usar la misma imagen (a menudo como íconos ), y debido al rendimiento, por supuesto queremos reutilizar la misma imagen , para que podamos guardará algo de memoria para otro uso. En general, la imagen reutilizada se usa a menudo en el elemento ui que nuestro usuario puede utilizar muchas veces . Por lo tanto, nos conviene reutilizarlo. Así que puede optar por utilizar el método imageNamed .

Y, por otro lado, en una aplicación, habrá algún elemento de UI que estará allí durante el ciclo de vida de la aplicación, como un botón, una vista de logotipo, por lo que estas imágenes utilizadas por estos elementos de la interfaz de usuario también pueden estar allí durante la aplicación ciclo de vida, no consideraría si estas imágenes deberían ser caché o no. Así que puede elegir utilizar el método imageNamed .


Por el contrario, en una aplicación, a menudo hay algunos elementos de la interfaz de usuario creados dinámicamente. Por ejemplo, nuestra aplicación admite fondo dynamic, de modo que el usuario puede elegir el fondo que le gusta. Y el fondo puede ser una imagen. Así que podemos tener una interfaz que enumere muchos antecedentes diferentes (a menudo se muestran mediante UIImageView ) para que el usuario elija , podemos nombrar la vista de lista MyBackgroundListView . Una vez que el usuario elige una imagen de fondo, se debe destruir MyBackgroundListView , porque ha terminado su función. La próxima vez que el usuario quiera cambiar su fondo, podemos crear MyBackgroundListView nuevamente. Por lo tanto, las imágenes utilizadas por MyBackgroundListView no deben almacenarse en caché, o la memoria de nuestra aplicación se agotará. Por lo tanto, esta vez debe usar el método imageWithContentsOfFile .

Como afirma el documento de Apple Apoyando pantallas de alta resolución en Views

En dispositivos con pantallas de alta resolución, los métodos imageNamed:, imageWithContentsOfFile:, e initWithContentsOfFile: buscan automáticamente una versión de la imagen solicitada con el modificador @ 2x en su nombre. Si encuentra uno, carga esa imagen en su lugar. Si no proporciona una versión de alta resolución de una imagen determinada, el objeto de imagen aún carga una imagen de resolución estándar (si existe) y la escala durante el dibujo.

entonces usted se preocuparía por la ruta de búsqueda de la imagen para el problema de la pantalla retina. IOS lo ayudará a manejarlo.

Disculpa mi pobre ingles . Puede ser útil.

Si no desea que su imagen se almacene en caché, también puede usar initWithContentsOfFile directamente:

 NSString *fileLocation = [[NSBundle mainBundle] pathForResource:fileName ofType:extension]; UIImage* yourImage = [[[UIImage alloc] initWithContentsOfFile:imagePath] autorelease]; 

También me han dicho que [UIImage imageNamed:] hace un poco de almacenamiento en caché, y las imágenes no se suelen lanzar. Me dijeron que tuviera cuidado de usarlo.

imageWithData es útil cuando almacena su imagen binaria en una base de datos o descarga progresivamente una imagen grande desde la web.

No usaría el nombre de la imagen si tu aplicación tiene muchas imágenes grandes que no son lo mismo. Experimenté un locking de la aplicación debido al uso excesivo de la misma.

No creo que la imagen se guarde en absoluto, y no sé por qué todos dicen eso. UIImage es una subclase de NSObject que utiliza contadores de referencia para realizar un seguimiento de las cosas con las que está relacionado. Entonces, cuando cargas una imagen, hace lo mismo. Si carga la misma imagen varias veces, tendrá (o debería) tener solo una copia de la imagen en la memoria y simplemente incrementará el contador de referencia cada vez que tenga que usar algo con esa imagen. Por los contadores de referencia quiero decir que cuando el recuento llega a 0 se elimina a sí mismo. así que “alloc”, “retener” son cada uno +1 al recuento y “release” es -1. No solo es una mejor forma de administrar la memoria, sino que este estilo de progtwigción también ayuda a limpiar las pérdidas de memoria.