iOS解決滑動(dòng)頁(yè)面卡頓的基本技巧
引言
在開(kāi)發(fā)中我們常常會(huì)遇到布局比較復(fù)雜的cell,在滑動(dòng)的時(shí)候會(huì)導(dǎo)致界面不流暢,出現(xiàn)卡頓的現(xiàn)象,這是由于CPU計(jì)算和GPU渲染,之間未及時(shí)交換數(shù)據(jù)丟失幀導(dǎo)致的結(jié)果。
imageView盡量設(shè)置為不透明
- opque盡量設(shè)置為YES
當(dāng)imageView的opque設(shè)置為YES的時(shí)候其alpha的屬性就會(huì)無(wú)效,imageView的半透明取決于其圖片半透明或者imageView本身的背景色合成的圖層view是半透明的。
如果圖片全部不是半透明就不會(huì)觸發(fā)圖層的blend操作,整個(gè)圖層就會(huì)不透明。
如果疊加的圖片有出現(xiàn)半透明的,就會(huì)立馬觸發(fā)圖層的blend操作,整個(gè)圖層不透明。
- opque設(shè)為NO
當(dāng)opque為NO的時(shí)候,圖層的半透明取決于圖片和其本身合成的圖層為結(jié)果。
- 背景色盡可能設(shè)為alpha值為1
當(dāng)某一塊圖層的alpha和其superView的背景色alpha不一樣的時(shí)候會(huì)觸發(fā)alpha合成操作,這是一項(xiàng)看似很簡(jiǎn)單但卻是非常消耗CPU性能的操作。至于alpha疊加
的概念如果有問(wèn)題可以查看官方說(shuō)法。
UIView的背景色設(shè)置
UIView的背景色盡量不要設(shè)置為clearColor,這樣也會(huì)觸發(fā)alpha疊加,在tableView滑動(dòng)的時(shí)候是非常消耗性能的。子視圖的背景色盡可能設(shè)置成其superView的背景色,這樣圖層合成的時(shí)候不會(huì)觸發(fā)blend操作。
-
最好不使用帶alpha通道的圖片,如果有alpha盡量讓美工取消alpha通道。
alpha通道的概念特地請(qǐng)教了下公司UI MM,是透明的意思。
cell上layer盡量避免使用圓角
- 在工作中關(guān)于滑動(dòng)界面我們會(huì)時(shí)常遇到cell行設(shè)置頭像為圓角等需求,這時(shí)候我們盡量避免使用
layder.cornerRadius
,因?yàn)檫@會(huì)觸發(fā)離屏渲染。離屏渲染很耗時(shí)間。
離屏渲染:是GPU渲染區(qū)的一個(gè)渲染緩沖區(qū),我們所用的所有顯示屏的圖形圖像都是通過(guò)GPU進(jìn)行渲染,然后顯示在屏幕上。GPU負(fù)責(zé)渲染會(huì)把渲染的圖形放到緩沖區(qū)然后CPU就會(huì)發(fā)一個(gè)垂直信號(hào)顯示到屏幕。
-
如果要使用圓角,我們可以設(shè)置為
layer.shouldRasterize = YES
,其實(shí)這個(gè)設(shè)置是觸發(fā)光柵化,可以大大提高渲染的性能。我的理解光柵化就是類(lèi)似于cell的重用機(jī)制。光柵化:把第一次渲染好的圖層放到緩沖區(qū),那么下次不需要再離屏渲染直接就可以從緩沖區(qū)拿去使用。
優(yōu)化圖片的加載方式
我們都知道圖片的加載方式有兩種形式:
1、UIImage *headerImage = [UIImage imageNamed:@"haodf.png";
2、UIImage * headerImage = [UIImage imageWithContentOfFile:@"haodf.png"];
我們講講兩種加載圖片方式的區(qū)別:
- 第一種:當(dāng)我們經(jīng)常需要這張圖片并且僅僅是小圖的時(shí)候,我們可以使用此種方式加載圖片。
這種方式是把圖片緩存在圖片緩存區(qū),當(dāng)我們使用的時(shí)候會(huì)通過(guò)圖片的名字也就是通過(guò)key的方式去查找圖片在緩存區(qū)的內(nèi)存地址。
當(dāng)我們使用很多圖片的時(shí)候系統(tǒng)就會(huì)開(kāi)辟很多內(nèi)存來(lái)存儲(chǔ)圖片,所以qq、微信我們很多時(shí)候都會(huì)去清除緩存操作。
- 第二種:當(dāng)我們使用工程里面的一張大圖并且使用次數(shù)很少甚至為1次的時(shí)候,我們優(yōu)先會(huì)采用這種方式加載圖片,這種方式當(dāng)使用完圖片的時(shí)候會(huì)立即丟棄釋放資源,所以對(duì)性能不會(huì)帶來(lái)負(fù)擔(dān)。
盡量延遲圖片的加載
-
當(dāng)我們?cè)诨瑒?dòng)頁(yè)面的時(shí)候尤其對(duì)于那種布局特別復(fù)雜的cell,滑動(dòng)的時(shí)候不要加載圖片,當(dāng)滑動(dòng)挺值得時(shí)候再進(jìn)行圖片的加載。
我們都知道不管是UITableView還是ScrollView在滾動(dòng)的時(shí)候需要顯示東西都是通過(guò)runLoop去拿。
當(dāng)滾動(dòng)的時(shí)候runLoop會(huì)處于NSRunLoopTrackingMode的模式,我們可以通過(guò)一個(gè)主線(xiàn)程隊(duì)列dispatch_after或者selfPerformSelector設(shè)置runLoop的模式為NSDefaultRunLoopMode模式,就可以做到停止?jié)L動(dòng)再加載圖片。
注:其實(shí)嚴(yán)格意義上selfPerformSelector的事件就是在主線(xiàn)程隊(duì)列中等待。
-
優(yōu)先加載理念
一直很好奇
墨跡天氣
這款app基本都是很炫的圖片,是如何做到滑動(dòng)時(shí)候不卡頓的呢,在cocoachina上有幸認(rèn)識(shí)了一位墨跡天氣的大牛,說(shuō)是采用優(yōu)先加載的理念,既先展示一部分,當(dāng)滑動(dòng)的時(shí)候再加載下面的一部分這樣就保持流暢。至于具體沒(méi)透露。
最重要的一點(diǎn)就是避免阻塞主線(xiàn)程
- 讓圖片的繪制、圖片的下載、對(duì)象的創(chuàng)建、文本的渲染等這些耗時(shí)的操作盡可能采用子線(xiàn)程異步的方式去處理,對(duì)于layer及UI的操作不得不在主線(xiàn)程里面,只能想辦法優(yōu)化,所以此處給大家推薦Facebook的得力之作ASDK,有興趣的可以好好研究下,現(xiàn)在好多公司都進(jìn)行采用。
爭(zhēng)議最多的xib、storyBoard、純代碼的問(wèn)題
蘋(píng)果推出storyboard確實(shí)為開(kāi)發(fā)者節(jié)省了大量的時(shí)間,提高了開(kāi)發(fā)效率,但是對(duì)于那種
復(fù)雜的滑動(dòng)界面,利用storyboard是非常消耗資源的,不信的可以試試用性能工具timeProfie看看cpu所占的性能百分比,其CPU的資源遠(yuǎn)遠(yuǎn)大于純代碼布局,我看了一個(gè)國(guó)外的網(wǎng)站介紹,這兩種方式初始化對(duì)象分配內(nèi)存的先后方式完全不一樣,至于具體細(xì)節(jié)有興趣的可以找相關(guān)資料研究。當(dāng)然對(duì)于那種重用性不強(qiáng)固定不怎么變化的界面還是很喜歡storyboard,一蹴而就,節(jié)省成本。
備注
以上都是在項(xiàng)目中遇到這些現(xiàn)象的思考和想法,如果有不對(duì)的地方,請(qǐng)加以糾正,謝謝!
author: lije