tldr: ImagedNamed в порядке. Он хорошо обрабатывает память. Используйте это и перестаньте беспокоиться.
Изменить ноябрь 2012 г.: обратите внимание, что этот вопрос относится к iOS 2.0! С тех пор требования к изображениям и их обработка сильно изменились. Retina увеличивает размер изображений и немного усложняет их загрузку. Благодаря встроенной поддержке изображений iPad и Retina вам непременно следует использовать ImageNamed в своем коде. А теперь для потомков:
родственная ветка на форумах разработчиков Apple привлекла больше внимания. В частности, Ринсвинд добавил некоторые полномочия.
В 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]];
}
Ринсвинд также включил несколько примеров кода для создания вашей собственной оптимизированной версии. Я не вижу, чтобы оно того стоило, но здесь оно для полноты картины.
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);
Компромисс с этим кодом заключается в том, что декодированное изображение использует больше памяти, но рендеринг происходит быстрее.
person
Rog
schedule
02.06.2009