在 iOS 上,UIImage 方法 imageNamed:
以两种方式优化图像加载:
第一种优化以存储(加载)时间来换取(内存)空间。
对于现有作为 UIImage 对象的图像,第二种优化可以节省时间和空间;无需加载或解码图像,也不会有重复的副本占用内存。
CZSharedImage 是一个小型库,为使用 UIImage#imageWithContentsOfFile:
和 UIImage#imageWithData:
加载的图像提供第二种优化。
请注意,CZSharedImage 不是一个缓存;它仅跟踪活着的 UIImage 对象。其价值体现在图像在视图中多次使用时(例如,表格视图中的辅助图像),或在导航层次结构中多次使用时。
CZSharedImage 需要 ARC 和 iOS 6.0。(它使用 6.0 中引入的 NSMapTable 类。)
导入头文件 CZSharedImage.h。
有关使用示例,请参阅 CZSharedImageTests.m 或 示例应用程序。
在示例应用程序中,屏幕上显示了 100 个 500x500 的图像实例(每个在解码时占用约 1MB 的内存)。使用 UIImage#imageWithContentsOfFile:
时,应用程序的驻留内存比使用 CZSharedImage#imageWithContentsOfFile:
时多 99MB。
使用 CZSharedImage 类创建共享图像。
+ (UIImage *)imageWithContentsOfFile:(NSString *)path;
+ (UIImage *)imageWithData:(NSData *)data;
+ (UIImage *)imageWithData:(NSData *)data scale:(CGFloat)scale;
只需将上述三个 UIImage 方法的调用替换为相同名称的 CZSharedImage 方法即可。如果相关的 UIImage 对象已经存在于运行的应用程序中,该方法将立即返回对该对象的引用。如果没有,它将通过相应的 UIImage 初始化器按常规加载。
UIImage *image = [CZSharedImage imageWithContentsOfFile:@"/path/to/image/file"];
请注意,在加载使用 imageWithData:
的图像的情况下,后续请求使用数据的 MD5 哈希进行匹配。一种更有效的方法是手动将图像与所选路径关联;有关详细信息,请参阅下一节。
+ (UIImage *)imageForPath:(NSString *)path;
+ (void)setImage:(UIImage *)image forPath:(NSString *)path;
对于不是通过三种imageWith...方法(例如,通过网络)加载图片的情况,手动将其关联到路径(如后续请求的URL)仍然可行。
// Try to get a reference to this image.
NSString *path = @"http://example.com/foo.png";
UIImage *image = [CZSharedImage imageForPath:path];
// If not available, fetch the image and associate it with the URL.
// (Error handling not shown.)
if (!image) {
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:path]];
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
{
// While the fetched UIImage object below remains alive,
// CZSharedImage#imageForPath: will return a reference to it.
UIImage *image = [UIImage imageWithData:data];
[CZSharedImage setImage:image forPath:path];
...
}];
}
...
同样,从数据库获取的图片可以与对应的数据库行(如果需要,还有列)的唯一路径关联。
// Try to get a reference to this image.
int personid = <...get row ID...>;
NSString *path = [NSString stringWithFormat:@"db:/person/%d", personid];
UIImage *image = [CZSharedImage imageForPath:path];
// If not available, fetch the image and associate it with the path.
// (Error handling not shown.)
if (!image) {
NSData *data = <...load image data...>;
// While the fetched UIImage object below remains alive,
// CZSharedImage#imageForPath: will return a reference to it.
UIImage *image = [CZSharedImage imageWithData:data];
[CZSharedImage setImage:image forPath:path];
}
...