我们都知道UIImage imageNamed:方法的神秘幕后缓存机制.在Apple的UIImage类参考中,它说:
在内存不足的情况下,可以从UIImage对象中清除图像数据以释放系统上的内存.此清除行为仅影响UIImage对象内部存储的图像数据,而不影响对象本身.当您尝试绘制其数据已被清除的图像时,图像对象会自动从其原始文件重新加载数据.然而,这个额外的负载步骤可能会导致很小的性能损失.
实际上,正如文档所示,图像数据不会"从UIImage对象中清除以释放系统上的内存".相反,应用程序会收到内存警告,直到它"因内存压力"退出.
编辑:在Xcode项目中使用传统的图像文件引用时,UIImage缓存工作正常.只是当您转换到资产目录时,内存永远不会被释放.
我实现了一个带有几个UIImageViews的UIScrollView来滚动浏览一长串图像.滚动时,正在加载下一个图像并将其分配给UIImageView的image属性,删除之前保存的UIImage的强链接.
由于imageNamed:缓存机制,我很快就耗尽了内存,应用终止时分配了大约170 MB的内存.
当然,有很多有趣的解决方案可以实现自定义缓存机制,包括覆盖imageNamed:类别中的类方法.通常,使用imageWithContentOfFile:不缓存图像数据的类方法,就像Apple开发人员在WWDC 2011上所建议的那样.
这些解决方案适用于常规图像文件,但您必须获得不像我希望的那样优雅的路径和文件扩展名.
我使用Xcode 5中引入的新资产目录,以利用根据设备和高效图像文件存储有条件地加载图像的机制.截至目前,似乎没有直接的方法从资产目录加载图像而不使用imageNamed:,除非我错过了一个明显的解决方案.
你们是否已经找到了资产目录的UIImage缓存机制?
我想在UIImage上实现一个类似于以下内容的类别:
static NSCache *_cache = nil;
@implementation UIImage (Caching)
+ (UIImage *)cachedImageNamed:(NSString *)name {
if (!_cache) _cache = [[NSCache alloc] init];
if (![_cache objectForKey:name]) {
UIImage *image = ???; // load image from Asset Catalog without internal caching mechanism
[_cache setObject:image forKey:name];
}
return [_cache objectForKey:name];
}
+ (void)emptyCache …Run Code Online (Sandbox Code Playgroud) 正如许多人抱怨的那样,在用于Retina显示器的Apple SDK中,似乎存在一个错误,而imageWithContentsOfFile实际上并不会自动加载2x图像.
我偶然发现了一个很好的帖子,如何制作一个能够检测UIScreen比例因子并正确加载低或高分辨率图像的功能(http://atastypixel.com/blog/uiimage-resolution-independence-and-the-iphone-4s -retina-display /),但该解决方案加载2x图像并仍然将图像的比例因子设置为1.0,这导致2倍图像缩放2倍(因此,比它看起来大4倍)
imageNamed似乎可以准确地加载低分辨率和高分辨率图像,但对我来说不是一个选择.
有没有人有一个解决方案来加载低/高分辨率图像不使用imageNamed或imageWithContentsOfFile的自动加载?(或者最终解决方法如何使imageWithContentsOfFile工作正确)