優(yōu)化的本質(zhì)
就是提高滾動的性能并減少內(nèi)存的使用,以保證流暢性蜓竹,本質(zhì)上就是降低CPU和GPU花費(fèi)的時間。
CPU:對象的創(chuàng)建和銷毀储藐、對象屬性的調(diào)整俱济、頁面布局、文本的計(jì)算和排版钙勃、圖片的格式轉(zhuǎn)換和編碼解碼蛛碌、圖像的繪制等。
GPU:頂點(diǎn)著色(對位圖bitmap處理)辖源、圖元裝配 蔚携、光柵化、片段著色克饶、片段處理酝蜒,這些提交到緩沖區(qū)中frameBuffer
設(shè)備的屏幕刷新率大概是60幀每秒,一幀約16.7毫秒矾湃,當(dāng)下一幀已經(jīng)到來的時候亡脑,當(dāng)前幀CPU、GPU的工作還沒有完成邀跃,就會感覺到卡頓霉咨。
優(yōu)化方案
CPU層
1、使用輕量級對象
用不到事件處理的view使用CALayer拍屑,UIView中也有CALayer屬性途戒,他們的本質(zhì)區(qū)別在于是否能響應(yīng)事件。CALayer更接近底層的渲染丽涩,直接使用CALayer可以減少一些UIView帶來的額外計(jì)算棺滞。
2、cell重用機(jī)制
注冊重用標(biāo)識符矢渊,等待使用隊(duì)列、使用中的隊(duì)列
初始化生成最初的使用中的cell枉证,并分配重用標(biāo)識符矮男。
滾動時,不可見的cell移除屏幕室谚,進(jìn)入到等待使用的隊(duì)列中(重用池)毡鉴。
當(dāng)新的cell要在屏幕中顯示時崔泵,先dequeueReusableCellWithIdentifier根據(jù)標(biāo)識符獲取一個可重用的(先在重用池中查找,有直接返回猪瞬,沒有新建憎瘸,并添加到使用中的隊(duì)列中)
獲取到cell后,根據(jù)數(shù)據(jù)更新cell
3陈瘦、避免cell重新布局
cell布局填充等操作是比較費(fèi)時的幌甘,一般創(chuàng)建的時候就把相關(guān)控件添加好,根據(jù)顯示/隱藏更新cell
減少cell中控件數(shù)量和層級痊项,若有樣式區(qū)別很大锅风,創(chuàng)建不同的cell
4、不在cellForRowAtIndexPath方法中做耗時操作
耗時操作有:
讀/寫文件鞍泉、cell執(zhí)行addSubview添加view皱埠、數(shù)據(jù)處理等。滑動過程中咖驮,這個方法會不停的被調(diào)用边器。
5、提前計(jì)算好布局
如果是高度固定的托修,直接設(shè)置rowHeight屬性效率更高饰抒,因?yàn)闆]有詢問代理的過程。注意:若設(shè)置代理返回告訴诀黍,設(shè)置rowHeight將無效袋坑。
如果高度不固定,使用estimatedRowHeight預(yù)估一個高度并配合autolayout實(shí)現(xiàn)正常顯示cell的目的眯勾。
根據(jù)tableview的方法執(zhí)行順序以此是:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
可以在willDisplayCell方法中緩存行高枣宫,heightForRowAtIndexPath中做出判斷
??:數(shù)據(jù)源更新時,記得更新緩存的高度
有一個緩存行高很不錯的開源庫
FDTemplateLayoutCell 相關(guān)詳情可以參考Tableview高度計(jì)算那些事
使用runloop實(shí)現(xiàn)空閑時間執(zhí)行預(yù)緩存(提前把未顯示出的cell高度緩存下來)
6吃环、圖片尺寸合適
圖片的size和UIImageView的size保持一致也颤,圖片通過contentMode處理顯示對tablView頻繁滾動還是會造成一定的影響。
網(wǎng)絡(luò)下載的圖片根據(jù)要顯示的圖片大小壓縮成合適大小的圖郁轻,每次只顯示處理過大小的圖翅娶,服務(wù)器處理好圖片
/// 根據(jù)指定frame裁剪image
+ (UIImage *)hf_cutImage:(UIImage *)origalImage frame:(CGRect)cropRect {
CGImageRef tmp = CGImageCreateWithImageInRect([origalImage CGImage], cropRect);
UIImage *resultImage = [UIImage imageWithCGImage:tmp scale:origalImage.scale orientation:origalImage.imageOrientation];
CGImageRelease(tmp);
return resultImage;
}
7、子線程處理耗時操作
文本處理(尺寸計(jì)算好唯、繪制等)
圖片處理(解碼竭沫、繪制等)
GPU層
1、減少視圖數(shù)量骑篙、層級和混合操作
當(dāng)多個視圖疊加蜕提,放在上面的視圖是半透明的時候,GPU就會進(jìn)行混合靶端,把透明的顏色放在下面的視圖的顏色谎势,混合之后得出一個顏色再顯示在屏幕上凛膏,會增加GPU的消耗。
UIView的背景色不要設(shè)置clearColor脏榆,圖片避免使用帶alpha通道的圖片猖毫。
2、盡量避免離屏渲染
光柵化须喂,layer.shouldRasterize = YES;
遮罩吁断,layer.mask;
圓角镊折,同時設(shè)置layer.masksToBouns = YES 和layer.cornerRadius>0;
陰影胯府,layer.shadow;
透明度,layer.allowsGroupOpacity = YES和layer.opacity<1
重寫drawRect方法優(yōu)化:
1恨胚、使用貝塞爾曲線配合Core Graphics框架繪制圓角或使用圓角圖片作為中間層
2骂因、設(shè)置shadowPath指定陰影效果路徑,減少視圖輪廓計(jì)算
3赃泡、異步進(jìn)行l(wèi)ayer渲染