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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM