標籤:
Apple官方文檔對於載入image提供了兩個方法
+ (nullable UIImage *)imageNamed:(NSString *)name;
+ (nullable UIImage *)imageWithContentsOfFile:(NSString *)path;
那麼這兩個方法對於載入圖片有什麼區別呢,下面我們用序列幀動畫來示範這兩個方法的區別:
這個程式一共載入了三組序列幀動畫:
首先我們使用+ (nullable UIImage *)imageNamed:(NSString *)name;來載入圖片
當我們把程式運行起來的時候,看下程式記憶體:
當我點擊第一組的時候,看下記憶體
接下來,我繼續點擊第二組,播放第二組序列幀的動畫
接下來我點擊第三組,播放第三組序列幀動畫
那麼我們接下來分析記憶體是為什麼增長到這麼多,而且當程式啟動並執行時候一直不會釋放掉
當執行self.imageView.animationImages = nmArray;就會對數組進行強引用,從而數組裡面的內容不會被釋放。所以圖片就會一直在記憶體中不會被釋放掉。
當時當我點擊另外一組序列幀圖片的時候,這個數組會指向另外一組圖片,那麼以前指向的圖片應該就會被釋放掉了。如果是這樣的話,記憶體不會持續增漲,而是當前數組
指向的一組圖片的記憶體大小而已。實際現象是這個記憶體是一直增漲的,所以當animationImages這個指標指向別的圖片數組時,它以前指向的圖片數組並沒有在記憶體中釋放,
而是放到了緩衝區中。才會造成記憶體一直增漲,圖片不會被釋放。很顯然,我們希望數組指向另外一個圖片數組的時候,要把以前指向的圖片數組釋放掉,從而釋放記憶體。
這裡就涉及到兩種載入圖片的方法的區別了。接下來我們來看一下用+ (nullable UIImage *)imageWithContentsOfFile:(NSString *)path;這種方式來載入圖片,
再次看一下記憶體效果
只是換了一種圖片載入方式,別的代碼沒有做任何改動。接下來看一下記憶體
同樣當我點擊第一組序列幀的時候,
當我點第二組序列幀動畫時:
當我點擊第三組圖片的時候:
這兩種載入圖片的方法的區別 ,在記憶體方面 ,看起來就顯而易見了。
那麼這兩種載入圖片的方式到底存在著怎麼樣的區別呢。上面我們說了,當使用+ (nullable UIImage *)imageNamed:(NSString *)name這種方式載入圖片時,當
圖片沒有指標指向的時候,並不會被釋放掉,而是放在了緩衝區中,所以記憶體就會一直增加。而使用+ (nullable UIImage *)imageWithContentsOfFile:(NSString *)path
這種方式載入圖片的時候,當圖片沒有指標指向的時候,就會被釋放掉。所以記憶體就不會一直增加。
那麼,這兩種載入圖片的方法,要看不同的情景。當圖片會被多次使用的時候,並且圖片比較小的時候,我們就使用+ (nullable UIImage *)imageNamed:(NSString *)name
這種方式載入,因為圖片被緩衝的緩衝區的時候,下一次再使用該圖片的時候,載入的效率就會提高了。當圖片不經常使用,並且圖片比較大的時候,就使用+ (nullable UIImage *)imageWithContentsOfFile:(NSString *)path這種方式載入,當圖片使用完畢,直接釋放掉。因為圖片基本不會被重複使用,使用者很少對一組序列幀動圖看好幾次吧。
通過記憶體的對比,這兩種載入圖片的區別就顯而易見了。
接下來,還有一個小問題,就是當一組序列幀播放完畢的時候,如果不點擊別的序列幀動畫,這個數組就一直會指向這個圖片數組。那麼就會導致最後一組序列幀圖片不會被釋放,
一直有強指標指向。
這個時候序列幀動畫播放完畢了,而記憶體還一直是280M,所以當序列幀動畫播放完畢的時候,我們要把self.imageView.animationImages這個指標指向Nil.從而釋放掉圖片
這樣,對於序列幀動畫的記憶體問題就已經全部解決了。
總結:當對於圖片要經常使用的時候,並且圖片比較小,我們就使用imageName方式載入,比如tableViewCell裡面的小表徵圖之類的,或者按鈕圖片。
當圖片不經常使用的時候,就使用ImageWithContentOfFile來載入,圖片使用結束以後,直接釋放掉,沒有必要再繼續占記憶體了。比如 序列幀動畫
iOS 載入Image的兩種方式