tldr: ImagedNamed está bien. Maneja bien la memoria. Úsalo y deja de preocuparte.
Editar noviembre de 2012 : tenga en cuenta que esta pregunta data de iOS 2.0. Los requisitos y el manejo de las imágenes han cambiado mucho desde entonces. Retina hace que las imágenes sean más grandes y cargarlas un poco más complejo. Con el soporte integrado para imágenes de iPad y retina, ciertamente debería usar ImageNamed en su código. Ahora, por el bien de la posteridad:
El hilo hermano de los foros de desarrolladores de Apple recibió un mejor tráfico. Específicamente, Rincewind agregó algo de autoridad.
Hay problemas en iPhone OS 2.x en los que el caché imageNamed: no se borra, incluso después de una advertencia de memoria. Al mismo tiempo, + imageNamed: se ha utilizado mucho no por la caché, sino por la conveniencia, que probablemente ha magnificado el problema más de lo que debería haber sido.
mientras advierte que
En el frente de la velocidad, hay un malentendido general de lo que está sucediendo. Lo más importante que hace + imageNamed: es decodificar los datos de la imagen del archivo de origen, lo que casi siempre aumenta significativamente el tamaño de los datos (por ejemplo, un archivo PNG del tamaño de una pantalla puede consumir unas pocas docenas de KB cuando se comprime, pero consume más de medio MB descomprimido - ancho * alto * 4). Por el contrario, + imageWithContentsOfFile: descomprimirá esa imagen cada vez que se necesiten los datos de la imagen. Como puede imaginar, si solo necesita los datos de la imagen una vez, no ha ganado nada aquí, excepto para tener una versión en caché de la imagen colgando, y probablemente por más tiempo del que necesita. Sin embargo, si tiene una imagen grande que necesita volver a dibujar con frecuencia, existen alternativas, aunque la que recomendaría principalmente es evitar volver a dibujar esa imagen grande :).
Con respecto al comportamiento general de la caché, la caché se basa en el nombre de archivo (por lo que dos instancias de + imageNamed: con el mismo nombre deberían dar como resultado referencias a los mismos datos en caché) y la caché crecerá dinámicamente a medida que solicite más imágenes a través de + imageNamed :. En iPhone OS 2.xa, el error evita que la caché se reduzca cuando se recibe una advertencia de memoria.
y
Tengo entendido que + imageNamed: caché debe respetar las advertencias de memoria en iPhone OS 3.0. Pruébelo cuando tenga la oportunidad e informe los errores si descubre que este no es el caso.
Así que ahí lo tienes. imageNamed: no romperá sus ventanas ni asesinará a sus hijos. Es bastante simple pero es una herramienta de optimización. Lamentablemente, tiene un nombre incorrecto y no hay equivalente que sea tan fácil de usar; por lo tanto, la gente lo usa en exceso y se molesta cuando simplemente hace su trabajo.
Agregué una categoría a UIImage para solucionar eso:
// header omitted
// Before you waste time editing this, please remember that a semi colon at the end of a method definition is valid and a matter of style.
+ (UIImage*)imageFromMainBundleFile:(NSString*)aFileName; {
NSString* bundlePath = [[NSBundle mainBundle] bundlePath];
return [UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"%@/%@", bundlePath,aFileName]];
}
Rincewind también incluyó un código de ejemplo para crear su propia versión optimizada. No veo que valga la pena el mantenimiento, pero aquí está por completo.
CGImageRef originalImage = uiImage.CGImage;
CFDataRef imageData = CGDataProviderCopyData(
CGImageGetDataProvider(originalImage));
CGDataProviderRef imageDataProvider = CGDataProviderCreateWithCFData(imageData);
CFRelease(imageData);
CGImageRef image = CGImageCreate(
CGImageGetWidth(originalImage),
CGImageGetHeight(originalImage),
CGImageGetBitsPerComponent(originalImage),
CGImageGetBitsPerPixel(originalImage),
CGImageGetBytesPerRow(originalImage),
CGImageGetColorSpace(originalImage),
CGImageGetBitmapInfo(originalImage),
imageDataProvider,
CGImageGetDecode(originalImage),
CGImageGetShouldInterpolate(originalImage),
CGImageGetRenderingIntent(originalImage));
CGDataProviderRelease(imageDataProvider);
UIImage *decompressedImage = [UIImage imageWithCGImage:image];
CGImageRelease(image);
La compensación con este código es que la imagen decodificada usa más memoria pero la renderización es más rápida.