TableView為什么會(huì)卡?
主要由以下原因:
cellForRowAtIndexPath:方法中處理了過(guò)多業(yè)務(wù)
tablev
iewCell的subview層級(jí)太復(fù)雜,做了大量透明處理
cell的height動(dòng)態(tài)變化時(shí)計(jì)算方式不對(duì)
優(yōu)化核心思想:UITableViewCell重用機(jī)制
簡(jiǎn)單的理解就是:UITableView只會(huì)創(chuàng)建一屏幕(或一屏幕多一點(diǎn))的UITableViewCell,其他都是從中取出來(lái)重用的。每當(dāng)Cell滑出屏幕時(shí),就會(huì)放入到一個(gè)集合(或數(shù)組)中(這里就相當(dāng)于一個(gè)重用池),當(dāng)要顯示某一位置的Cell時(shí),會(huì)先去集合(或數(shù)組)中取,如果有,就直接拿來(lái)顯示;如果沒(méi)有,才會(huì)創(chuàng)建。這樣做的好處可想而知,極大的減少了內(nèi)存的開(kāi)銷(xiāo)。
Tips:
提前計(jì)算并緩存好高度(布局),因?yàn)閔eightForRowAtIndexPath:是調(diào)用最頻繁的方法;
異步繪制,遇到復(fù)雜界面,參考Facebook的AsyncDisplayKit和YYAsyncLayer異步繪制框架;
緩存圖片(SDWebImage),提前處理好UIImageView圖片的尺寸按需加載而不是加載原圖;
計(jì)算等耗時(shí)操作異步處理,處理完再回主線(xiàn)程更新UI;
圖文混排不定高度采用CoreText排版,緩存Cell高度參考YYKit;
實(shí)現(xiàn)Cell的drawRect:方法直接繪制,減少UIView,UIImageView,UILabel等容器的使用。
Bonus:
正確使用reuseIdentifier來(lái)重用Cell;
盡量少用或不用透明圖層或View;
如果Cell內(nèi)現(xiàn)實(shí)的內(nèi)容來(lái)自web,使用異步加載,緩存請(qǐng)求結(jié)果;
減少subviews的數(shù)量在heightForRowAtIndexPath:中盡量不使用cellForRowAtIndexPath:,如果你需要用到它,只用一次然后緩存結(jié)果;
盡量少用addView給Cell動(dòng)態(tài)添加View,可以初始化時(shí)就添加,然后通過(guò)hide來(lái)控制是否顯示;
固定高度不要實(shí)現(xiàn)heightForRowAtIndexPath:方法。
1.UITableViewCell里不要添加太多subview,最好只添加一個(gè)cellview。
2.UITableViewCell 上的子View的opaque屬性設(shè)為YES。其實(shí)默認(rèn)也是不透明。UITableViewCell盡量不要包含透明的子View。
3.在cellview里,重寫(xiě)drawRect函數(shù)繪制UITableViewCell的內(nèi)容。
4.在繪制字符串時(shí),盡可能使用drawAtPoint: withFont:,而不要使用更復(fù)雜的drawAtPoint:(CGPoint)point forWidth:(CGFloat)width withFont:(UIFont *)font lineBreakMode:(UILineBreakMode)lineBreakMode; 如果要繪制過(guò)長(zhǎng)的字符串,建議自己先截?cái)?,然后使用drawAtPoint: withFont:方法繪制。
5.在繪制圖片時(shí),盡量使用drawAtPoint,而不要使用drawInRect。drawInRect如果在繪制過(guò)程中對(duì)圖片進(jìn)行放縮,會(huì)特別消耗CPU。
6.如果繪制cell過(guò)程中,需要下載cell中的圖片,建議在繪制cell一段時(shí)間后再開(kāi)啟圖片下載任務(wù)。譬如先畫(huà)一個(gè)默認(rèn)圖片,然后在0.5S后開(kāi)始下載本cell的圖片。
7.即使下載cell 圖片是在子線(xiàn)程中進(jìn)行,在繪制cell過(guò)程中,也不能開(kāi)啟過(guò)多的子線(xiàn)程。最好只有一個(gè)下載圖片的子線(xiàn)程在活動(dòng)。否則也會(huì)影響UITableViewCell的繪制,因而影響了UITableViewCell的滑動(dòng)速度。(建議結(jié)合使用NSOpeartion和NSOperationQueue來(lái)下載圖片,如果想盡可能找的下載圖片,可以把[self.queuesetMaxConcurrentOperationCount:4];)
8.最好自己寫(xiě)一個(gè)cache,用來(lái)緩存UITableView中的UITableViewCell,這樣在整個(gè)UITableView的生命周期里,一個(gè)cell只需繪制一次,并且如果發(fā)生內(nèi)存不足,也可以有效的釋放掉緩存的cell。
9.不要將tableview的背景顏色設(shè)置成一個(gè)圖片。這回嚴(yán)重影響UITableView的滑動(dòng)速度。在限時(shí)免費(fèi)搜索里,我曾經(jīng)翻過(guò)一個(gè)錯(cuò)誤:self.tableView_.backgroundColor = [UIColorcolorWithPatternImage:[UIImageimageNamed:@"background.png"]]; 通過(guò)這種方式設(shè)置UITableView的背景顏色會(huì)嚴(yán)重影響UTIableView的滑動(dòng)流暢性。修改成`self.tableView_.backgroundColor` = [UIColor clearColor];之后,fps從43上升到60左右?;瑒?dòng)比較流暢。
10.cell的行高不是固定值,需要計(jì)算,則要盡可能緩存行高值,避免重復(fù)計(jì)算行高。這里指的是UITableViewDelegate里的行高函數(shù)。
如果做到以上10點(diǎn),則UITableView 滑動(dòng)的fps可以達(dá)到60 fps?;瑒?dòng)非常順暢