UIKit: UIImage

UIImage對象是iOS中用來顯示圖像數(shù)據(jù)的高級接口。我們可以從文件,NSData,Quartz圖片對象中創(chuàng)建UIImage對象??梢哉f這個類是我們接觸頻率非常高的一個類。

UIImage的不可變性

UIImage對象是不可變的,所以一旦創(chuàng)建后,我們就不能再改變它的屬性。這也就意味著,我們只能在初始化方法中提供屬性值或依賴于圖片自身的屬性值。同樣,由于其不可變,所以在任何線程中都可以安全地使用它。

如果我們想修改UIImage對象的一些屬性,則可以使用便捷方法和自定義的參數(shù)值來創(chuàng)建圖像的一份拷貝。

另外,由于UIImage對象是不可變的,所以它沒有提供訪問底層圖片數(shù)據(jù)的方法。不過我們可以使用UIImagePNGRepresentation或UIImageJPEGRepresentation方法來獲取包含PNG或JPG格式的數(shù)據(jù)的NSData對象。如下代碼所示:

創(chuàng)建UIImage對象

對于一個UIImage對象來說,它的數(shù)據(jù)源主要有以下幾種:

文件:我們可以使用init(contentsOfFile:)方法來從指定文件中創(chuàng)建對象。

純圖片數(shù)據(jù)(NSData):如果在內(nèi)存中有圖片的原始數(shù)據(jù)(表示為NSData對象),則可以使用init(data:)來創(chuàng)建。需要注意的是這個方法會對象圖片數(shù)據(jù)做緩存。

CGImage對象:如果我們有一個CGImage對象,則可以使用init(CGImage:)或init(CGImage:scale:orientation:)創(chuàng)建UIImage對象。

CIImage對象:如果我們有一個CIImage對象,則可以使用init(CIImage:)或init(CIImage:scale:orientation:)創(chuàng)建UIImage對象。

需要注意的是,如果是從文件或者純圖片數(shù)據(jù)中創(chuàng)建UIImage對象,則要求對應(yīng)的圖片格式是系統(tǒng)支持的圖片類型。

對于Objective-C來說,UIImage對象也提供了這些初始化方法對應(yīng)的便捷類方法來創(chuàng)建對象。

內(nèi)存管理

在實際的應(yīng)用中,特別是圖片類應(yīng)用中,我們可能需要使用大量的圖片。我們都知道,圖片通常都是非常占內(nèi)存的。如果同一時間加載大量的圖片,就可能占用大量的系統(tǒng)內(nèi)存。

為此,Apple采用了一種比較巧妙的策略。在低內(nèi)存的情況下,系統(tǒng)會強制清除UIImage對象所指向的圖片數(shù)據(jù),以釋放部分內(nèi)存。注意,這種清除行為影響到的只是圖片數(shù)據(jù),而不會影響到UIImage對象本身。當我們需要繪制那些圖片數(shù)據(jù)已經(jīng)被清除的UIImage對象時,對象會自動從源文件中重新加載數(shù)據(jù)。當然,這是以時間換空間的一種策略,會導(dǎo)致一定的性能損耗。

說到這里,我們不得不提一下init(named:)方法了??梢哉f我們平時創(chuàng)建UIImage對象用得最多的應(yīng)該就是這個方法。這個方法主要是使用bundle中的文件創(chuàng)建圖片的快捷方式。關(guān)于這個方法,有幾點需要注意:

緩存:這個方法會首先去系統(tǒng)緩存中查找是否有圖片名對應(yīng)的圖片。如果有就返回緩存中的圖片;如果沒有,則該方法從磁盤或者asset catalog中加載圖片并返回,同時將圖片緩存到系統(tǒng)中。緩存的圖片只有在收到內(nèi)存警告時才會釋放。因此,如果圖片的使用頻率比較低,則可以考慮使用imageWithContentsOfFile:方法來加載圖片,這樣可以減少內(nèi)存資源的消耗。當然,這需要權(quán)衡考慮,畢竟讀寫磁盤也是有性能消耗的,而且現(xiàn)在的高端機內(nèi)存已經(jīng)不小了。

多分辨率圖片處理:在iOS 4.0后,該方法會根據(jù)屏幕的分辨率來查找對應(yīng)尺寸的圖片。即我們使用時,只需要寫圖片名,而不需要指定是1x, 2x還是3x圖,該方法會自己判斷。

png圖片后綴:在iOS 4.0以后,如果圖片是png格式的,則圖片文件名不需要附帶擴展名。

線程安全性:該方法在iOS 9.0之前并不是線程安全的,在二級線程中調(diào)用可能會導(dǎo)致崩潰。在iOS 9.0之后,Apple作了優(yōu)化處理,將其改為線程安全的方法。為了避免不必要的麻煩,盡量在主線程中調(diào)用這個方法。

這個方法通過一個UIEdgeInsets來指定上下左右不變形的寬度或高度。它會返回一個新的圖像。而如果圖像被拉伸,則會以平鋪的方式來處理中間的拉伸區(qū)域。

圖片大小的限制

UIImage對象使用的圖片大小盡量小于1024*1024。因為這么大的圖片消耗的內(nèi)存過大,在將其作為OpenGL中的貼圖或者是繪制到view/layer中時,可以會出現(xiàn)問題。如果僅僅是代碼層面的操作的話,則沒有這個限制。比如,將一個大于1024*1024的圖片繪制到位圖圖形上下文中以重新設(shè)定其大小。事實上,我們需要通過這種操作來改變圖片大小,以將其繪制到視圖中。

支持的圖片格式

UIImage支持的圖片格式在UIImage Class Reference中列出來了,大家可以直接參考。

需要注意的一點是RGB-565格式的BMP文件在加載時會被轉(zhuǎn)換成ARGB-1555格式。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容