在我們的開發(fā)中常常會遇到頁面卡頓的情況苍匆,頁面卡頓多數(shù)是由于CPU計算與GPU渲染,之間未及時交換數(shù)據(jù)丟失幀導致识藤!
imageView盡量設(shè)置為不透明
opque盡量設(shè)置為YES
當imageView的opque設(shè)置為YES的時候其alpha的屬性就會無效笋妥,imageView的半透明取決于其圖片半透明或者imageView本身的背景色合成的圖層view是半透明的。
如果圖片全部不是半透明就不會觸發(fā)圖層的blend操作爽蝴,整個圖層就會不透明。
如果疊加的圖片有出現(xiàn)半透明的纫骑,就會立馬觸發(fā)圖層的blend操作蝎亚,整個圖層不透明。
opque設(shè)為NO
當opque為NO的時候先馆,圖層的半透明取決于圖片和其本身合成的圖層為結(jié)果发框。
背景色盡可能設(shè)為alpha值為1
當某一塊圖層的alpha和其superView的背景色alpha不一樣的時候會觸發(fā)alpha合成操作,這是一項看似很簡單但卻是非常消耗CPU性能的操作煤墙。至于alpha疊加的概念如果有問題可以查看官方說法梅惯。
UIView的背景色設(shè)置
UIView的背景色盡量不要設(shè)置為clearColor宪拥,這樣也會觸發(fā)alpha疊加,在tableView滑動的時候是非常消耗性能的铣减。子視圖的背景色盡可能設(shè)置成其superView的背景色她君,這樣圖層合成的時候不會觸發(fā)blend操作。
最好不使用帶alpha通道的圖片葫哗,如果有alpha盡量讓美工取消alpha通道缔刹。
alpha通道的概念特地請教了下公司UI MM,是透明的意思。
cell上layer盡量避免使用圓角
在工作中關(guān)于滑動界面我們會時常遇到cell行設(shè)置頭像為圓角等需求劣针,這時候我們盡量避免使用layder.cornerRadius校镐,因為這會觸發(fā)離屏渲染。離屏渲染很耗時間酿秸。
離屏渲染:是GPU渲染區(qū)的一個渲染緩沖區(qū)灭翔,我們所用的所有顯示屏的圖形圖像都是通過GPU進行渲染,然后顯示在屏幕上辣苏。GPU負責渲染會把渲染的圖形放到緩沖區(qū)然后CPU就會發(fā)一個垂直信號顯示到屏幕肝箱。
如果要使用圓角,我們可以設(shè)置為layer.shouldRasterize = YES稀蟋,其實這個設(shè)置是觸發(fā)光柵化煌张,可以大大提高渲染的性能。我的理解光柵化就是類似于cell的重用機制退客。
光柵化:把第一次渲染好的圖層放到緩沖區(qū)骏融,那么下次不需要再離屏渲染直接就可以從緩沖區(qū)拿去使用。
優(yōu)化圖片的加載方式
我們都知道圖片的加載方式有兩種形式:
UIImage *Image = [UIImage imageNamed:@"helloworld"萌狂;
UIImage *Image = [UIImage imageWithContentOfFile:@"helloworld"];
我們講講兩種加載圖片方式的區(qū)別:
第一種:當我們經(jīng)常需要這張圖片并且僅僅是小圖的時候档玻,我們可以使用此種方式加載圖片。
這種方式是把圖片緩存在圖片緩存區(qū)茫藏,當我們使用的時候會通過圖片的名字也就是通過key的方式去查找圖片在緩存區(qū)的內(nèi)存地址误趴。
當我們使用很多圖片的時候系統(tǒng)就會開辟很多內(nèi)存來存儲圖片,所以qq务傲、微信我們很多時候都會去清除緩存操作凉当。
第二種:當我們使用工程里面的一張大圖并且使用次數(shù)很少甚至為1次的時候,我們優(yōu)先會采用這種方式加載圖片售葡,這種方式當使用完圖片的時候會立即丟棄釋放資源看杭,所以對性能不會帶來負擔。
盡量延遲圖片的加載
當我們在滑動頁面的時候尤其對于那種布局特別復雜的cell挟伙,滑動的時候不要加載圖片楼雹,當滑動挺值得時候再進行圖片的加載。
我們都知道不管是UITableView還是ScrollView在滾動的時候需要顯示東西都是通過runLoop去拿。
當滾動的時候runLoop會處于NSRunLoopTrackingMode的模式烘豹,我們可以通過一個主線程隊列dispatch_after或者selfPerformSelector設(shè)置runLoop的模式為NSDefaultRunLoopMode模式瓜贾,就可以做到停止?jié)L動再加載圖片。
注:其實嚴格意義上selfPerformSelector的事件就是在主線程隊列中等待携悯。
優(yōu)先加載理念
在一些很酷炫的app中,看起來一次性要加載很多東西筷笨,其實不然憔鬼,他們采用的是優(yōu)先加載,即需要時再加載胃夏。
最重要的一點就是避免阻塞主線程
讓圖片的繪制轴或、圖片的下載、對象的創(chuàng)建仰禀、文本的渲染等這些耗時的操作盡可能采用子線程異步的方式去處理照雁,對于layer及UI的操作不得不在主線程里面,只能想辦法優(yōu)化答恶,所以此處給大家推薦Facebook的得力之作ASDK饺蚊,有興趣的可以好好研究下,現(xiàn)在好多公司都進行采用悬嗓。
爭議最多的xib污呼、storyBoard、純代碼的問題
蘋果推出storyboard確實為開發(fā)者節(jié)省了大量的時間包竹,提高了開發(fā)效率燕酷,但是對于那種
復雜的滑動界面,利用storyboard是非常消耗資源的捌袜,不信的可以試試用性能工具timeProfie看看cpu所占的性能百分比锥涕,其CPU的資源遠遠大于純代碼布局相寇,我看了一個國外的網(wǎng)站介紹,這兩種方式初始化對象分配內(nèi)存的先后方式完全不一樣酱讶,至于具體細節(jié)有興趣的可以找相關(guān)資料研究。
當然對于那種重用性不強固定不怎么變化的界面還是很喜歡storyboard双絮,一蹴而就浴麻,節(jié)省成本。
不要重復創(chuàng)建不必要的table cell囤攀。
前面說了软免,UITableView只需要一屏幕的UITableViewCell對象即可。因此在cell不可見時焚挠,可以將其緩存起來膏萧,而在需要時繼續(xù)使用它即可。
而UITableView也提供了這種機制,只需要簡單地設(shè)置一個identifier即可:
static NSString *CellIdentifier = @"xxx"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];if (cell == nil) { cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; }
值得一提的是榛泛,cell被重用時蝌蹂,它內(nèi)部繪制的內(nèi)容并不會被自動清除,因此你可能需要調(diào)用setNeedsDisplayInRect:或setNeedsDisplay方法曹锨。
此 外孤个,在添加table cell的時候,如果不需要動畫效果沛简,最好不要使用insertRowsAtIndexPaths:withRowAnimation:方法齐鲤,而是直接調(diào) 用reloadData方法。因為前者會對所有indexPaths調(diào)用tableView:cellForRowAtIndexPath:方法椒楣,即便該 cell并不需要顯示(不知道是不是bug)给郊,這就可能創(chuàng)建大量多余的cell∨趸遥勘誤:只是在模擬器上測試如此淆九,真機調(diào)試時沒有這種bug。
減少視圖的數(shù)目毛俏。
UITableViewCell包含了textLabel炭庙、detailTextLabel和imageView等view,而你還可以自定義一些視圖放在它的contentView里拧抖。然而view是很大的對象煤搜,創(chuàng)建它會消耗較多資源,并且也影響渲染的性能唧席。
如果你的table cell包含圖片擦盾,且數(shù)目較多,使用默認的UITableViewCell會非常影響性能淌哟。奇怪的是迹卢,使用自定義的view,而非預(yù)定義的view徒仓,明顯會快些腐碱。
當然,最佳的解決辦法還是繼承UITableViewCell掉弛,并在其drawRect:中自行繪制:
- (void)drawRect:(CGRect)rect { if (image) { [image drawAtPoint:imagePoint]; self.image = nil; } else { [placeHolder drawAtPoint:imagePoint]; } [text drawInRect:textRect withFont:font lineBreakMode:UILineBreakModeTailTruncation]; }
不過這樣一來症见,你會發(fā)現(xiàn)選中一行后,這個cell就變藍了殃饿,其中的內(nèi)容就被擋住了谋作。最簡單的方法就是將cell的selectionStyle屬性設(shè)為UITableViewCellSelectionStyleNone,這樣就不會被高亮了乎芳。
此 外還可以創(chuàng)建CALayer遵蚜,將內(nèi)容繪制到layer上帖池,然后對cell的contentView.layer調(diào)用addSublayer:方法。這個例 子中吭净,layer并不會顯著影響性能睡汹,但如果layer透明,或者有圓角寂殉、變形等效果囚巴,就會影響到繪制速度了。解決辦法可參見后面的預(yù)渲染圖像不撑。
不要做多余的繪制工作文兢。
在實現(xiàn)drawRect:的時候,它的rect參數(shù)就是需要繪制的區(qū)域焕檬,這個區(qū)域之外的不需要進行繪制。
例如上例中澳泵,就可以用CGRectIntersectsRect实愚、CGRectIntersection或CGRectContainsRect判斷是否需要繪制image和text,然后再調(diào)用繪制方法兔辅。
預(yù)渲染圖像腊敲。
你會發(fā)現(xiàn)即使做到了上述幾點,當新的圖像出現(xiàn)時维苔,仍然會有短暫的停頓現(xiàn)象碰辅。解決的辦法就是在bitmap context里先將其畫一遍,導出成UIImage對象介时,然后再繪制到屏幕