標籤:
imageNamed和dataWithContentsOfFile的區別
imagecacheuiviewextensionprocessingxcode
最近老是受iphone記憶體問題的困擾,找了些資料,現在貼出了兩篇經典的博文。博文如下:
轉載自:http://blog.csdn.net/hj2060/article/details/6925926
最近做一個寫真書,由於載入大量的圖片,記憶體溢出,程式崩潰,卻不報任何錯誤或者警告。
用xcode的instrument工具查看記憶體使用量情況時,發現程式使用記憶體情況很穩定維持在1.3M左右,也沒有記憶體流失。那麼問題來了,程式無故退出肯定是記憶體溢出了,而instrument並顯示沒有溢出(一般單個程式記憶體消耗唯20M左右會發警告,30M程式崩潰退出)。所以一直在想是不是哪個地方忘記釋放記憶體了,經過仔細檢查,並不存在沒有釋放的記憶體啊,糾結了一天。最後終於找到問題所在了,是[UIImage [email protected]""]在搞鬼;
翻看了一些網上資料http://www.cocoachina.com/bbs/simple/?t36896.html,總結一下UIImage的記憶體使用量及管理
用UIImage載入映像的方法很多,最常用的是下面兩種:
1.用imageNamed函數
複製代碼
[UIImage imageNamed:ImageName];
2.用NSData的方式載入,例如:
複製代碼
NSString *filePath = [[NSBundle mainBundle] pathForResource:fileName ofType:extension];
NSData *image = [NSData dataWithContentsOfFile:filePath];
[UIImage imageWithData:image];
由於第一種方式要寫的代碼比較少,可能比較多人利用imageNamed的方式載入映像。其實這兩種載入方式都有各自的特點。
1)用imageNamed的方式載入時,系統會把映像Cache到記憶體。如果映像比較大,或者映像比較多,用這種方式會消耗很大的記憶體,而且釋放映像的記憶體是一件相對來說比較麻煩的事情。例如:如果利用imageNamed的方式載入映像到一個動態數組NSMutableArray,然後將將數組賦予一個UIView的對象的animationImages進行逐幀動畫,那麼這將會很有可能造成記憶體泄露。並且釋放映像所佔據的記憶體也不會那麼簡單。但是利用imageNamed載入映像也有自己的優勢。對於同一個映像系統只會把它Cache到記憶體一次,這對於映像的重複利用是非常有優勢的。例如:你需要在一個TableView裡重複載入同樣一個表徵圖,那麼用imageNamed載入映像,系統會把那個表徵圖Cache到記憶體,在Table裡每次利用那個映像的時候,只會把圖片指標指向同一塊記憶體。這種情況使用imageNamed載入映像就會變得非常有效。
2)利用NSData方式載入時,映像會被系統以資料方式載入到程式。當你不需要重用該映像,或者你需要將映像以資料方式儲存到資料庫,又或者你要通過網路下載一個很大的映像時,請盡量使用imageWithData的方式載入映像。
無論用哪種方式載入映像,映像使用結束後,一定要記得顯示釋放記憶體。
所以當程式要載入大量圖片時贏盡量使用第二種方法。
下面貼出另一篇部落格:
http://blog.csdn.net/sing_sing/article/details/6707163
前段時間完成的一個iPad應用,近來測試發現一個問題,在iPad運行大量其他應用程式時很容易出現內容警告而導致程式退出。找了一些資料,發現用起來方便的+ (UIImage *)imageNamed:(NSString *)name,卻存在一個很嚴重的記憶體釋放問題,它所佔用的內容不被釋放,即使其所在的view已經release了。看完之後一陣後怕,皆因程式中使用UIImage基本都是使用這種方法擷取。事不宜遲,馬上對代碼進行最佳化。由於手頭暫時沒有裝置測試,測試效果稍候再分析。
轉載一篇很好的文章:
+ (UIImage *)imageNamed:(NSString *)name導致的記憶體問題
這種方法在application bundle的最上層資料夾尋找名字的圖象 , 如果找到圖片, 系統緩衝圖象。圖片內容被載入到系統記憶體中,使用時直接引用到系統記憶體。
所以當圖片比較大時,程式使用的記憶體會迅速上升導致記憶體警告並退出。
特別在使用Interface Builder建立介面時,如果直接拖動UIImageView 並設定image的圖片名稱。InterfaceBuilder 正是通過UIImage 類的imageName方法載入圖片。圖片被緩衝,導致記憶體使用量較大。且無法釋放,即使release掉 UIImageView也無濟於事。
所以推薦使用+ (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/
imageNamed和dataWithContentsOfFile的區別(1)