tldr: ImagedNamed は問題ありません。メモリをうまく処理します。それを使用して、心配するのをやめてください。
2012 年 11 月の編集: この質問は iOS 2.0 のものであることに注意してください。それ以来、画像の要件と処理は大きく変わりました。Retina では画像が大きくなり、読み込みが少し複雑になります。iPad および Retina 画像のサポートが組み込まれているため、必ずコード内で ImageNamed を使用する必要があります。さて、後世のために:
Apple Dev Forumsの姉妹スレッドは、より良いトラフィックを受け取りました。具体的には、 Rincewindがいくつかの権限を追加しました。
iPhone OS 2.x には、メモリ警告の後でも imageNamed: キャッシュがクリアされないという問題があります。同時に、+imageNamed: はキャッシュのためではなく利便性のために多くの用途を獲得しており、おそらく問題を本来よりも拡大しています。
と警告しながら
速度の面では、何が起こっているのかについて一般的な誤解があります。+imageNamed: が行う最大のことは、ソース ファイルから画像データをデコードすることです。これにより、ほとんどの場合、データ サイズが大幅に増大します (たとえば、画面サイズの PNG ファイルは、圧縮すると数十 KB を消費する可能性がありますが、0.5 MB 以上を消費します)。解凍 - 幅 * 高さ * 4)。対照的に、 +imageWithContentsOfFile: は、画像データが必要になるたびにその画像を解凍します。ご想像のとおり、画像データが 1 回だけ必要な場合は、キャッシュされたバージョンの画像が必要以上に長く使用されることを除いて、ここでは何も得られません。ただし、頻繁に再描画する必要がある大きな画像がある場合は、代替手段がありますが、主にその大きな画像の再描画を避けることをお勧めします:)。
キャッシュの一般的な動作に関しては、ファイル名に基づいてキャッシュします (したがって、同じ名前の +imageNamed: の 2 つのインスタンスは、同じキャッシュ データへの参照になるはずです)。 +imageNamed:. iPhone OS 2.x では、バグにより、メモリ警告が受信されたときにキャッシュが縮小されません。
と
私の理解では、+imageNamed: キャッシュは iPhone OS 3.0 のメモリ警告を尊重する必要があります。機会があればテストして、そうでない場合はバグを報告してください。
それで、あなたはそれを持っています。imageNamed: 窓を壊したり、子供を殺したりしません。とてもシンプルですが、最適化ツールです。悲しいことに、それはひどく名前が付けられており、これほど使いやすい同等のものはありません。
それを修正するためにUIImageにカテゴリを追加しました:
// 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 には、独自の最適化されたバージョンを構築するためのサンプル コードも含まれています。メンテナンスする価値があるとは思えませんが、完全を期すためにここに示します。
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);
このコードのトレードオフは、デコードされたイメージがより多くのメモリを使用することですが、レンダリングはより高速になります。