tldr: 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 также включил пример кода для создания своей собственной оптимизированной версии. Я не вижу, что оно того стоит, но вот для полноты.
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);
Компромисс с этим кодом заключается в том, что декодированное изображение использует больше памяти, но рендеринг выполняется быстрее.