Ответ 1
TL;DR: ImagedNamed в порядке. Он хорошо справляется с памятью. Используйте его и перестаньте беспокоиться.
Изменить ноябрь 2012. Обратите внимание, что этот вопрос относится к iOS 2.0! С тех пор требования к изображениям и обработка сильно изменились. Retina делает изображения более крупными и загружает их немного сложнее. Благодаря встроенной поддержке изображений iPad и сетчатки, вы обязательно должны использовать ImageNamed в своем коде. Теперь, ради потомства:
сестра-нить на форумах Apple Dev получила некоторый лучший трафик. В частности Rincewind добавил некоторые полномочия.
В iPhone OS 2.x есть проблемы, в которых кеш imageNamed: не будет очищен даже после предупреждения о памяти. В то же время + imageNamed: получил много пользы не для кеша, а для удобства, что, вероятно, увеличило проблему больше, чем должно было быть.
предупреждая, что
На фронте скорости есть общее непонимание того, что происходит. Самая большая вещь, которую + imageNamed: делает, декодирует данные изображения из исходного файла, который почти всегда значительно раздувает размер данных (например, размер PNG файла с экраном может потреблять несколько десятков КБ при сжатии, но потребляет более половины МБ декомпрессированная - ширина * высота * 4). В отличие от + imageWithContentsOfFile: будет декомпрессировать это изображение каждый раз, когда нужны данные изображения. Как вы можете себе представить, если вам нужны только данные изображения один раз, вы ничего здесь не выиграли, за исключением того, что у вас есть кешированная версия изображения, висящая вокруг, и, вероятно, дольше, чем вам это нужно. Однако, если у вас есть большое изображение, которое вам нужно часто перерисовывать, тогда есть альтернативы, хотя я бы рекомендовал прежде всего избегать перерисовывания этого большого изображения:).
Что касается общего поведения кэша, он выполняет кэширование на основе имени файла (поэтому два экземпляра + imageNamed: с тем же именем должны приводить к ссылкам на одни и те же данные в кэше), и кеш будет динамически расти по мере запроса больше изображений с помощью + 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 также включил некоторый пример кода для создания собственной оптимизированной версии. Я не вижу, что это стоит maintentace, но здесь для полноты.
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);
Компромисс с этим кодом заключается в том, что декодированное изображение использует больше памяти, но рендеринг выполняется быстрее.