tldr: ImagedNamed в порядке. Он хорошо справляется с памятью. Используйте его и перестаньте беспокоиться.
Редактировать Ноябрь 2012 г.: Обратите внимание, что этот вопрос датируется iOS 2.0! С тех пор требования к изображениям и обработка сильно изменились. Retina делает изображения более крупными и загружает их немного сложнее. Благодаря встроенной поддержке изображений iPad и сетчатки, вы обязательно должны использовать ImageNamed в своем коде. Теперь, ради потомства:
sister thread на форумах Apple Dev получили некоторый лучший трафик. В частности, Rincewind добавил некоторые полномочия.
В iPhone OS 2.x есть проблемы, в которых кеш изображенияNamed: не будет очищен даже после предупреждения о памяти. В то же время + imageNamed: получил большую пользу не для кеша, а для удобства, что, вероятно, увеличило проблему больше, чем должно было быть.
одновременно предупреждая, что
На передней скорости, есть общее непонимание того, что происходит. Самая большая вещь, которую + imageNamed: делает, декодирует данные изображения из исходного файла, который почти всегда значительно раздувает размер данных (например, размер PNG-файла с экраном может потреблять несколько десятков КБ при сжатии, но потребляет более половины МБ декомпрессированная - ширина * высота * 4). В отличие от + imageWithContentsOfFile: будет декомпрессировать это изображение каждый раз, когда нужны данные изображения. Как вы можете себе представить, если вам нужны только данные изображения один раз, вы ничего здесь не выиграли, за исключением того, что у вас есть кешированная версия изображения, висящая вокруг, и, вероятно, дольше, чем вам это нужно. Однако, если у вас есть большое изображение, которое вам нужно часто перерисовывать, тогда есть альтернативы, хотя я бы рекомендовал в первую очередь избегать перерисовки этого большого изображения :).
Что касается общего поведения кеша, он выполняет кэширование на основе имени файла (поэтому два экземпляра + imageNamed: с тем же именем должны приводить ссылки на одни и те же кэшированные данные), и кеш будет динамически расти, так как вы запросить дополнительные изображения с помощью + imageNamed :. В iPhone OS 2.x ошибка предотвращает сжатие кеша при получении предупреждения о памяти.
и
Я понимаю, что + imageNamed: кэш должен соблюдать предупреждения памяти на iPhone OS 3.0. Проверьте это, когда вы получите шанс и сообщите об ошибках, если обнаружите, что это не так.
Итак, у вас оно есть. imageNamed: не будет разбивать ваши окна или убивать ваших детей. Это довольно просто, но это инструмент оптимизации. К сожалению, он плохо назван и нет equivaluent что проста в использовании - поэтому люди злоупотребляют его и расстраиваться, когда он просто делает свою работу
Я добавил категорию в 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);
Компромисс с этим кодом заключается в том, что декодированное изображение использует больше памяти, но рендеринг выполняется быстрее.
Я в напряжении. :) – Kriem
меня тоже. Кажется, что SO не так полна гениев, как я думал. –
Похоже, вы провели некоторое время, исследуя это. Провели ли вы какие-либо эксперименты, которые продемонстрировали бы какое-либо негативное влияние UIImage imageNamed на последнюю версию какао-touch? Создайте UITableView и добавьте много (много тысяч) строк и посмотрите, снижается ли производительность при отображении разных изображений в каждой строке. Может быть, тогда люди могут прокомментировать ваши выводы. – stefanB