imageNamed:
UIImage 的方法背后神秘的缓存机制我们都知道。在 Apple 的UIImage 类参考中它说:
在内存不足的情况下,可能会从 UIImage 对象中清除图像数据以释放系统上的内存。这种清除行为只影响 UIImage 对象内部存储的图像数据,而不影响对象本身。当您尝试绘制其数据已被清除的图像时,图像对象会自动从其原始文件重新加载数据。然而,这个额外的加载步骤可能会导致小的性能损失。
事实上,图像数据不会像文档所建议的那样“从 UIImage 对象中清除以释放系统上的内存”。相反,应用程序会收到内存警告,直到“由于内存压力”退出。
编辑:在您的 Xcode 项目中使用常规图像文件引用时,UIImage 缓存工作正常。只是当您转换到资产目录时,内存永远不会被释放。
我用几个 UIImageViews 实现了一个 UIScrollView 来滚动一长串图像。滚动时,正在加载下一个图像并将其分配给 UIImageView 的image
属性,从而删除之前持有的 UIImage 的强链接。
由于imageNamed:
's 的缓存机制,我很快就用完了内存,并且应用程序终止并分配了大约 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 {
[_cache removeAllObjects];
}
@end
更好的方法当然是更好地控制UIImage
的内部缓存以及在使用资产目录时在文档中描述的低内存条件下清除图像数据的可能性。
感谢您的阅读,我期待您的想法!