現(xiàn)在App的頁(yè)面越來(lái)越復(fù)雜,性能優(yōu)化成為了開(kāi)發(fā)當(dāng)中非常重要的一環(huán),并且對(duì)性能的追求越來(lái)越極致,本文將主要講述如何解決UILabel在顯示中文時(shí),像素混合的問(wèn)題,由于內(nèi)容不多,所以就不作目錄了,費(fèi)話不多說(shuō),馬上開(kāi)始。
首先補(bǔ)充一些基礎(chǔ)的知識(shí)點(diǎn)(以下知識(shí)點(diǎn),均在像素對(duì)齊的情形下),我們知道GPU是圖形硬件,主要的工作是混合紋理并算出像素的RGB值,這是一個(gè)非常復(fù)雜的計(jì)算過(guò)程,計(jì)算的過(guò)程越復(fù)雜,所需要消耗的時(shí)間就越長(zhǎng),GPU的使用率就越高,這并不是一個(gè)好的現(xiàn)像,而我們需要做的是減少GPU的計(jì)算量。
一個(gè)頁(yè)面可以只有一個(gè)視圖,也可以有很多視圖,每個(gè)視圖都會(huì)對(duì)應(yīng)著一個(gè)的底圖層,頁(yè)面上的所有圖層構(gòu)成了一個(gè)圖層樹(shù)(模型樹(shù)),這個(gè)圖層樹(shù)便是我們?cè)谄聊簧夏芸吹降囊磺械膩?lái)源,我們可以假設(shè)一個(gè)圖層(CALayer)就是一個(gè)紋理(Texture),接下來(lái),我會(huì)用圖層來(lái)替代紋理。如果當(dāng)前我們擁有一個(gè)和屏幕大小一致的單一圖層,那么屏幕上的每一個(gè)像素相當(dāng)于圖層中的一個(gè)像素,這個(gè)時(shí)候,我們?cè)谶@個(gè)圖層上放置一個(gè)完全不透明的圖層,那么GPU將會(huì)把上面的圖層合成到下面的圖層當(dāng)中,由于上面的是一個(gè)完全不透明的圖層,所以上面的圖層會(huì)部份遮蓋掉下面的圖層,而在遮蓋掉的矩形區(qū)域內(nèi),GPU會(huì)直接使用上面圖層的像素來(lái)顯示。如果我們最底的圖層上放置的是一個(gè)有透明度的圖層,那么在這個(gè)矩形區(qū)域里,GPU需要混合上下兩個(gè)圖層來(lái)計(jì)算出在屏幕上顯示出來(lái)的像素的RGB值。若在同一個(gè)區(qū)域內(nèi),存在著多個(gè)有透明度的圖層,那么GPU需要更多的計(jì)算才能得出最終像素的RGB值。而我們要做的就是避免像素混合,盡可能地為視圖設(shè)置背景色,且設(shè)置opaque為YES,這會(huì)大大減少GPU的計(jì)算。
本文的主角是UILabel,UILabel會(huì)將字符串與背景色繪制成位圖,并且顯示出來(lái),請(qǐng)看下圖。


接下來(lái)看一下像素混合的情況(可以通過(guò)模擬器的Debug中Color Blended Layers或Instruments中Core Animation的Color Blended Layers打開(kāi))。

都是綠色,表示沒(méi)有出現(xiàn)像素混合的情況,這時(shí)我們把label的背景設(shè)為透明。

上下兩個(gè)視圖變成了紅色,出現(xiàn)了像素混合的情況,表示在這兩個(gè)紅色的區(qū)域內(nèi),GPU需要做像素混合的計(jì)算,這無(wú)疑是增加了GPU的工作,所以在任何情況下,我們都應(yīng)該設(shè)置UILabel的背景色為不透明。
剛剛用來(lái)做測(cè)試的系統(tǒng)版本為iOS7,那么現(xiàn)在我們來(lái)看看iOS8的情況。

看上去跟iOS7的效果一樣,現(xiàn)在我們來(lái)看一下像素混合的情況。

文本區(qū)域是綠色,表示沒(méi)有像素混合,但顯示的是英文,接下來(lái)我們?cè)囍@示中文并看看像素混合的情況。

雖然設(shè)置了背景色,但在iOS8上用UILabel顯示中文卻出現(xiàn)了像素混合的情況,這是為什么呢?我們來(lái)看看UILabel在iOS8前后的變化,在iOS8以前,UILabel使用的是CALayer作為底圖層,而在iOS8開(kāi)始,UILabel的底圖層變成了_UILabelLayer,繪制文本也有所改變,就像上圖所視(在iOS8剛發(fā)布的時(shí)候,我一度懷疑Apple歧視中文)。
那怎么解決呢?首先我們來(lái)觀察一下上圖,從圖中我們可以看到在背景色的四周多了一圈透明的邊,而這一圈透明的邊明顯超出了圖層的矩形區(qū)域,既然發(fā)現(xiàn)這了一點(diǎn),那么解決方案就很明了了。

設(shè)置圖層的masksToBounds為YES時(shí),圖層將會(huì)沿著B(niǎo)ounds進(jìn)行裁剪,我們來(lái)看一下修改后的效果。

label變回了綠色,表示像素混合問(wèn)題已解決。
Tips:可以的話,要求美工在切圖的時(shí)候,一定不要切出那些留有透明區(qū)域的圖片,不然在你顯示圖片的時(shí)候,同樣會(huì)出現(xiàn)像素混合問(wèn)題。
本文旨在解決UILabel在iOS8及以后的系統(tǒng)版本中顯示中文像素混合的問(wèn)題,其它的性能優(yōu)化,像離屏渲染,像素對(duì)齊等,網(wǎng)上已有大量的技術(shù)文,本文再提及也是大同小異。如果文中有說(shuō)錯(cuò)的,還望指出,第一次寫(xiě)技術(shù)文,表述能力有限。
下期預(yù)告:由于現(xiàn)在App的頁(yè)面越來(lái)越復(fù)雜,有些頁(yè)面需要比較長(zhǎng)的時(shí)間來(lái)加載,下一篇技術(shù)文將會(huì)講述,在Push頁(yè)面時(shí)的性能優(yōu)化。
文/Delpan(簡(jiǎn)書(shū)作者)
原文鏈接:http://www.itdecent.cn/p/db6602413fa3
著作權(quán)歸作者所有,轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),并標(biāo)注“簡(jiǎn)書(shū)作者”。