tldr: ImagedNamed está bien. Maneja bien la memoria. Úselo y deja de preocuparte.
Editar Nov 2012: Tenga en cuenta que esta pregunta data de iOS 2.0! Los requisitos de imagen y manejo han avanzado mucho desde entonces. Retina hace las imágenes más grandes y las carga un poco más complejas. Con el soporte incorporado para imágenes de iPad y retina, seguramente deberías usar ImageNamed en tu código. Ahora, por la posteridad:
El sister thread en los foros de Apple Dev recibió algo de tráfico mejor. Específicamente Rincewind añadió algo de autoridad.
Hay problemas en el iPhone OS 2.x donde el caché imageNamed: no se borró, incluso después de una advertencia de memoria. Al mismo tiempo, + imageNamed: se ha utilizado mucho no para la memoria caché, sino para mayor comodidad, lo que probablemente ha magnificado el problema más de lo que debería haber sido.
aunque advierte de que
En el frente de la velocidad, hay un malentendido general de lo que está pasando. Lo más importante que + imageNamed: hace es decodificar los datos de imagen del archivo fuente, lo que casi siempre infla significativamente el tamaño de los datos (por ejemplo, un archivo PNG con tamaño de pantalla podría consumir unas pocas docenas de KB cuando está comprimido, pero consume más de medio MB descomprimido - ancho * alto * 4). Por contraste + imageWithContentsOfFile: descomprimirá esa imagen cada vez que se necesiten los datos de la imagen. Como puedes imaginar, si solo necesitas los datos de la imagen una vez, no has ganado nada aquí, excepto para tener una versión almacenada en caché de la imagen, y probablemente por más tiempo del que necesites. Sin embargo, si tiene una imagen grande que necesita volver a dibujar a menudo, existen alternativas, aunque la que recomiendo principalmente es evitar volver a dibujar esa imagen grande :).
Con respecto al comportamiento general de la memoria caché, la memoria caché se basa en el nombre de archivo (por lo que dos instancias de + imageNamed: con el mismo nombre deberían hacer referencia a los mismos datos en caché) y la memoria caché crecerá dinámicamente a medida solicitar más imágenes a través de + imageNamed :. En iPhone OS 2.x, un error impide que la memoria caché se reduzca cuando se recibe una advertencia de memoria.
y
Mi entendimiento es que el imageNamed +: caché debe respetar las advertencias de memoria en el iPhone OS 3.0. Pruébelo cuando tenga la oportunidad e informe de errores si encuentra que este no es el caso.
Así que, ahí lo tienes. imageNamed: no destruirá tus ventanas ni asesinará a tus hijos. Es bastante simple pero es una herramienta de optimización. Lamentablemente está mal nombrado y no hay equivaluent que es tan fácil de usar - por lo tanto la gente utilizarlo en exceso y se molestan cuando simplemente hace su trabajo
he añadido una categoría para UIImage de arreglar 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ó algunos códigos de ejemplo para construir su propia versión optimizada. No puedo ver que valga la pena el maintentace, pero aquí está para completar.
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 el procesamiento es más rápido.
Estoy en suspenso. :) – Kriem
yo también. Parece que SO no está tan lleno de genios como yo pensaba. –
Parece que has pasado algún tiempo investigando esto. ¿Has hecho algún experimento que muestre algún impacto negativo de UIImage imageNamed con la última versión de cocoa-touch? Cree una UITableView y agregue muchas (muchas) filas y vea si el rendimiento disminuye cuando muestra imágenes diferentes en cada fila. Quizás entonces las personas puedan comentar sus hallazgos. – stefanB