UIImage imageWithName:的使用优劣

[UIImage imageNamed:]只适合与UI界面中小的贴图的读取,而一些比较大的资源文件应该尽量避免使用这个接口。

直接读取文件路径[UIImage imageWithContentsOfFile]来解决图片的读取问题

这两种方式的主要区别在于:

imageName的方式会在使用的时候系统会cache,程序员是无法处理cache的,这是由系统自动处理的,对于重复加载的图像,速度会提升很多,这样反而用户体验好。所以如果某张图片需要在应用中使用多次,或者重复引用,使用imageName的方式会更好

imageWithContentsOfFile的方式,在使用完成之后系统会释放,不会缓存下来,所以也就没有这样的问题。一般也不会把所有的图片都会缓存。有些图片在应用中只使用一两次的,就可以用这样的方式,比如新手引导界面的图片等等,就适合这样的方式。没有明显的界限。

 

推荐使用+ (UIImage *)imageWithContentsOfFile:(NSString *)path方法加载图片。 

也可以重载 imageNamed方法。 

@implementation UIImage(imageNamed_Hack) 

+ (UIImage *)imageNamed:(NSString *)name { 

return [UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"%@/%@", [[NSBundle mainBundle] bundlePath], name ] ];


@end 

Note: With this override you will not have any cache loading UIImages, if you need this, 

you will have to implement your own cache. 

Tip: If your applications use much image processing, consider to use de PhotoshopFramework 

for iPhone. Check here: http://sourceforge.net/projects/photoshopframew/

 

explain here:
 

There are issues in iPhone OS 2.x where the imageNamed: cache would not be cleared, even after a memory warning. At the same time +imageNamed: has gotten a lot of use not for the cache, but for the convenience, which has probably magnified the problem more than it should have been.

 

On the speed front, there is a general misunderstanding of what is going on. The biggest thing that +imageNamed: does is decode the image data from the source file, which almost always significantly inflates the data size (for example, a screen sized PNG file might consume a few dozen KBs when compressed, but consumes over half a MB decompressed - width * height * 4). By contrast +imageWithContentsOfFile: will decompress that image everytime the image data is needed. As you can imagine, if you only need the image data once, you've won nothing here, except to have a cached version of the image hanging around, and likely for longer than you need it. However, if you do have a large image that you need to redraw often, then there are alternatives, although the one I would recommend primarily is to avoid redrawing that large image :).

With respect to the general behavior of the cache, it does cache based on filename (so two instances of +imageNamed: with the same name should result in references to the same cached data) and the cache will grow dynamically as you request more images via +imageNamed:. On iPhone OS 2.x a bug prevents the cache from being shrunk when a memory warning isreceived.

 

My understanding is that the +imageNamed: cache should respect memory warnings on iPhone OS 3.0. Test it when you get a chance and report bugs if you find that this is not the case.

 

So, there you have it. imageNamed: will not smash your windows or murder your children. It's pretty simple but it is an optimisation tool. Sadly it is badly named and there is no equivaluent that is as easy to use - hence people overuse it and get upset when it simply does its job

I added a category to UIImage to fix that:

// 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 also included some example code to build your own optimised version. I can't see it is worth the maintentace but here it is for completeness.

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

posted on 2012-12-17 14:13  easonoutlook  阅读(4225)  评论(0编辑  收藏  举报