消除UIImage图像-NAME:FUD

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (45)

很多人说imageNamed是不好的,但同样数量的人说性能很好--特别是在渲染时。

UIImageimageNamed方法用于泄漏,因此最好避免,但在最近的版本中已经修复。我想更好地理解缓存算法,以便做出一个合理的决定:我可以相信系统在哪里缓存我的图像,以及我需要在哪里多走一步,自己去做。我目前的基本理解是NSMutableDictionaryUIImages由文件名引用。它变得更大,当内存耗尽时,它变得更小。

例如,是否有人确切地知道后面的图像缓存imageNamed不回应didReceiveMemoryWarning是吗?苹果似乎不太可能不这么做。

提问于
用户回答回答于

iPhoneOS2.x中存在一些问题,即使在内存警告之后,ImageNmad:Cache也不会被清除。同时,+ImageNmad:已经得到了大量的使用,不是为了缓存,而是为了方便,这可能使问题变得比它应该的更大。

同时警告说

在速度方面,人们普遍对正在发生的事情产生误解。+ImageNmad:做的最大的事情是从源文件中解码图像数据,它几乎总是显着地膨胀数据大小(例如,一个屏幕大小的png文件在压缩时可能消耗几十kbs,但是消耗超过半MB解压的宽度)。*高度*4)。相反,+ImageWithContentsOfFile:将在每次需要图像数据时解压缩该图像。可以想象,如果您只需要图像数据一次,那么您在这里什么也没有赢,只会有一个缓存版本的图像在周围徘徊,并且可能比您需要的时间更长。但是,如果您确实有一个需要经常重绘的大图像,那么还有其他选择,尽管我主要推荐的是避免重绘那个大图像:)。 关于缓存的一般行为,它基于文件名(因此,两个+ImageNmad:同名的实例应该会导致对相同缓存数据的引用)缓存,并且缓存将动态增长,因为您通过+ImageNmad:请求更多的图像。在iPhoneOS2.x上,当接收到内存警告时,bug会防止缓存缩小。

我的理解是+ImageNmad:cache应该尊重iPhoneOS3.0上的内存警告。当你有机会的时候测试它,如果你发现不是这样的话,报告错误。

我在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);

这段代码的优点是解码后的图像使用更多内存,但呈现速度更快。

用户回答回答于

根据我的经验,ImageNmad创建的图像缓存不会响应内存警告。我有两个应用程序,我尽可能的精益,直到我的管理,但仍然莫名其妙地崩溃,因为缺乏mem。当我停止使用ImageNmad加载图像时,这两个应用程序变得非常稳定。

我承认,这两个应用程序都加载了一些较大的图像,但没有什么是完全不寻常的。在第一个应用程序中,我完全跳过缓存,因为用户不太可能两次返回同一个映像。在第二个过程中,我构建了一个非常简单的缓存类来完成您提到的事情--将UIImage保存在NSMutableDictionary中,然后在收到内存警告时刷新它的内容。如果ImageNmad:是这样的缓存,那么我就不应该看到任何性能升级。所有这些都是在2.2上运行的--我不知道这上面是否有3.0的含义。

扫码关注云+社区