tldr: ImagedNamed - це добре. Він добре обробляє пам'ять. Використовуйте його і перестаньте хвилюватися.
Редагувати листопад 2012 року : Зауважте, що це запитання дано iOS 2.0! З тих пір вимоги до зображення та обробку значно змінилися. Сітківка збільшує зображення і завантажує їх трохи складніше. Маючи вбудовану підтримку зображень iPad та сітківки, ви, звичайно, повинні використовувати ImageNamed у своєму коді. Тепер заради нащадків:
Сестра нитку на форумах Apple , Dev отримав кілька краще трафіку. Конкретно Рінсвінд додав певних повноважень.
В iPhone OS 2.x є проблеми, коли кеш imageNamed: кеш не буде очищено навіть після попередження пам'яті. У той же час + imageNamed: отримав багато користі не для кешу, а для зручності, що, ймовірно, збільшило проблему більше, ніж могло бути.
при цьому попереджуючи це
На фронті швидкості існує загальне нерозуміння того, що відбувається. Найголовніше, що має + imageNamed: - це декодування даних зображень із вихідного файлу, що майже завжди значно збільшує розмір даних (наприклад, PNG-файл розміром з екраном може споживати кілька десятків КБ при стисненні, але витрачає понад пів МБ декомпресія - ширина * висота * 4). На відміну від + imageWithContentsOfFile: буде декомпресувати це зображення кожного разу, коли потрібні дані зображення. Як ви можете собі уявити, якщо вам потрібні дані зображення лише один раз, ви нічого тут не виграєте, окрім того, що ви маєте кешовану версію зображення, що висить навколо, і, швидше за все, довше, ніж вам потрібно. Однак якщо у вас є велике зображення, яке потрібно часто перемальовувати, то є альтернативи, хоча одна, яку я рекомендував би в першу чергу, це уникати перемальовування цього великого зображення :).
Що стосується загальної поведінки кешу, він робить кеш, заснований на імені файлу (тому два екземпляри + imageNamed: з тим самим іменем повинні спричинити посилання на ті самі кешовані дані) і кеш буде динамічно зростати, коли ви запитаєте більше зображень через + imageNamed:. На iPhone OS 2.xa помилка запобігає зменшенню кешу при отриманні попередження про пам'ять.
і
Я розумію, що кеш + 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);
Компроміс із цим кодом полягає в тому, що декодоване зображення використовує більше пам'яті, але візуалізація відбувається швидше.