tldr: ImagedNamed está bem. Ele lida bem com a memória. Use-o e pare de se preocupar.
Editar novembro de 2012 : Observe que esta questão data do iOS 2.0! Os requisitos e o manuseio de imagens mudaram muito desde então. Retina torna as imagens maiores e carregá-las um pouco mais complexas. Com o suporte integrado para imagens de iPad e retina, você certamente deve usar ImageNamed em seu código. Agora, para o bem da posteridade:
O tópico irmão no Apple Dev Forums recebeu um tráfego melhor. Especificamente, Rincewind adicionou alguma autoridade.
Há problemas no iPhone OS 2.x em que o cache de imageNamed: não era apagado, mesmo após um aviso de memória. Ao mesmo tempo, + imageNamed: foi muito utilizado, não pelo cache, mas pela conveniência, o que provavelmente ampliou o problema mais do que deveria.
enquanto avisa que
Quanto à velocidade, existe um mal-entendido geral sobre o que está acontecendo. A maior coisa que + imageNamed: faz é decodificar os dados da imagem do arquivo de origem, o que quase sempre aumenta significativamente o tamanho dos dados (por exemplo, um arquivo PNG do tamanho de uma tela pode consumir algumas dezenas de KBs quando compactado, mas consome mais de meio MB descomprimido - largura * altura * 4). Em contraste, + imageWithContentsOfFile: descompactará a imagem sempre que os dados da imagem forem necessários. Como você pode imaginar, se precisar dos dados da imagem apenas uma vez, você não ganhou nada aqui, exceto por ter uma versão em cache da imagem perdida e provavelmente por mais tempo do que você precisa. No entanto, se você tem uma imagem grande que precisa redesenhar com frequência, existem alternativas, embora a que eu recomendaria principalmente é evitar redesenhar essa imagem grande :).
Com relação ao comportamento geral do cache, ele faz cache com base no nome do arquivo (portanto, duas instâncias de + imageNamed: com o mesmo nome devem resultar em referências aos mesmos dados em cache) e o cache crescerá dinamicamente conforme você solicita mais imagens via + imageNamed :. No iPhone OS 2.xa bug impede que o cache seja reduzido quando um aviso de memória é recebido.
e
Meu entendimento é que o + imageNamed: cache deve respeitar os avisos de memória no iPhone OS 3.0. Teste-o quando tiver oportunidade e relate os bugs se achar que não é o caso.
Então, aí está. imageNamed: não vai quebrar suas janelas ou matar seus filhos. É muito simples, mas é uma ferramenta de otimização. Infelizmente, ele é mal nomeado e não há equivalente que seja tão fácil de usar - portanto, as pessoas o abusam e ficam chateadas quando ele simplesmente faz seu trabalho
Eu adicionei uma categoria ao UIImage para corrigir isso:
// 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 também incluiu alguns códigos de exemplo para construir sua própria versão otimizada. Não consigo ver que vale a pena a manutenção, mas aqui é para ser 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);
A desvantagem desse código é que a imagem decodificada usa mais memória, mas a renderização é mais rápida.