什么樣的tableView是很優(yōu)異的朴译?
- 滾動時坏快,確保cell刷新幀率應(yīng)該在 50+/s !
- 展示cell時唯卖,不能出現(xiàn)跳幀現(xiàn)象粱玲,導(dǎo)致?lián)Q面不流暢。
- 最關(guān)鍵的是在創(chuàng)建cell或者從緩存池取cell時,讓系統(tǒng)花費(fèi)最少的時間,即盡可能的減少顯示cell的計(jì)算量耐床。
1. 行高要緩存
舉個簡單的栗子:如果現(xiàn)在要顯示100個Cell,當(dāng)前屏幕顯示5個。那么全局刷新UITableView時, UITableView會先調(diào)用100次tableView:heightForRowAtIndexPath:
方法,然后調(diào)用5次 tableView:cellForRowAtIndexPath:
方法;滾動屏幕時,每當(dāng)Cell滾入屏幕,都會調(diào)用 一次tableView:heightForRowAtIndexPath:
和tableView:cellForRowAtIndexPath:
方 法楔脯。所以說要提前計(jì)算并緩存好高度,因?yàn)?code>heightForRowAtIndexPath:是調(diào)用最頻繁的方法,如果是使用MVVM搭建框架,可以在viewModel中添加行高屬性,提前計(jì)算好行高撩轰。
如果是固定高度的cell,可以直接采用tableView.rowHeight = 88;
的方式昧廷,這樣寫堪嫂,就需要實(shí)現(xiàn)tableView:heightForRowAtIndexPath:
方法了;如果實(shí)現(xiàn)這個方法木柬,設(shè)置rowHeight
就會失效皆串。
2.不要動態(tài)創(chuàng)建子視圖
意思是:cell所有的子視圖都預(yù)先在初始化方法中創(chuàng)建,如果根據(jù)實(shí)際情況不需要顯示的可以設(shè)置 hidden.這樣能盡可能的減少cell創(chuàng)建或從緩存池取時因?yàn)椴季肿涌丶牡臅r間.
3. 渲染
為了保證TableView的流暢,當(dāng)快速滑動的時候眉枕,cell必須被快速的渲染出來恶复。所以cell渲染的速度必須快。如何提高cell的渲染速度呢速挑?
(1)當(dāng)有圖像時谤牡,預(yù)渲染圖像,在bitmap context先將其畫一遍姥宝,導(dǎo)出成UIImage對象翅萤,然后再繪制到屏幕,這會大大提高渲染速度腊满。具體內(nèi)容可以自行查找“利用預(yù)渲染加速顯示iOS圖像”相關(guān)資料套么。
(2)渲染最好時的操作之一就是混合(blending)了,所以我們不要使用透明背景培己,將cell的opaque
值設(shè)為Yes,背景色不要使用clearColor胚泌,盡量不要使用陰影漸變等
(3)由于混合操作是使用GPU來執(zhí)行省咨,我們可以用CPU來渲染志于,這樣混合操作就不再執(zhí)行徘六∨劣浚可以在UIView的drawRect方法中自定義繪制犯戏。
4.減少視圖的數(shù)目
當(dāng)cell上子視圖過多或者層級關(guān)系過于復(fù)雜的時候喻犁,cell的布局計(jì)算會大大增長动猬,可能會導(dǎo)致一個runloop流程渲染不及時腔寡,導(dǎo)致卡頓奈揍。
5.減少多余的繪制操作
在實(shí)現(xiàn)drawRect方法的時候绅项,它的參數(shù)rect就是我們需要繪制的區(qū)域紊册,在rect范圍之外的區(qū)域我們不需要進(jìn)行繪制,否則會消耗相當(dāng)大的資源快耿。
6.異步化UI囊陡,不要阻塞主線程
使用Texture∠坪ィ可以保持復(fù)雜用戶界面的流暢和響應(yīng)撞反。Texture的node是線程安全的,通過將圖像解碼搪花、文本繪制和渲染等操作從主線程中遷移遏片,從而保證主線程的響應(yīng)。
7. 不要給cell動態(tài)添加subView
在初始化cell的時候就將所有需要展示的添加完畢撮竿,然后根據(jù)需要來設(shè)置hidden
屬性顯示和隱藏吮便。
8. 懶加載圖片
快速滑動的時候,不要加載圖片幢踏,滑動停止時髓需,再加載圖片。這樣做可以防止在快速滑動時加載圖片導(dǎo)致的卡頓問題房蝉。
9. 圓角優(yōu)化
圓角的不合理使用僚匆,會導(dǎo)致離屏渲染,觸發(fā)緩沖區(qū)的頻繁合并和上下文的的切換搭幻。所以需要合理的設(shè)置視圖的圓角白热,避免離屏渲染。
使用貝塞爾曲線UIBezierPath和Core Graphics框架畫出一個圓角
UIImageView *imageView = [[UIImageView alloc]initWithFrame:CGRectMake(100, 100, 100, 100)];
imageView.image = [UIImage imageNamed:@"myImg"];
// 開始對imageView進(jìn)行畫圖
UIGraphicsBeginImageContextWithOptions(imageView.bounds.size, NO, 1.0);
// 使用貝塞爾曲線畫出一個圓形圖
[[UIBezierPath bezierPathWithRoundedRect:imageView.bounds cornerRadius:imageView.frame.size.width] addClip];
[imageView drawRect:imageView.bounds];
imageView.image = UIGraphicsGetImageFromCurrentImageContext();
// 結(jié)束畫圖
UIGraphicsEndImageContext();
[self.view addSubview:imageView];