UITableView幾乎是最常用的控件之一,在開發(fā)中,經(jīng)常需要對(duì)UITableView進(jìn)行性能調(diào)優(yōu),提高用戶體驗(yàn)
最基本的規(guī)則
- cell的復(fù)用
-
heightForRowAtIndexPath
在cellForRowAtIndexPath
之前調(diào)用,遵循UIScrollView中必須先計(jì)算contentSize-
cellForRowAtIndexPath
:僅僅當(dāng)cell顯示的時(shí)候才會(huì)調(diào)用 -
heightForRowAtIndexPath
:- 初始化的時(shí)候,如果有N行,那么會(huì)執(zhí)行N次
- 調(diào)用reloadData方法,又會(huì)執(zhí)行N次
- 顯示的cell又會(huì)調(diào)用該方法
-
盡量少的cell種類
由于復(fù)用機(jī)制的存在,假設(shè)cell有M種,一個(gè)屏幕能容下的cell個(gè)數(shù)為N個(gè),那么緩沖池中將會(huì)最多存在M x N個(gè)cell對(duì)象,而如果只有一種cell的話,最多只會(huì)有N個(gè)對(duì)象在緩存池中
定高的cell使用rowHeight
如果所有cell是統(tǒng)一高度的,那么避免使用代理方法去執(zhí)行多次,直接設(shè)置rowHeight屬性即可
提前計(jì)算并緩存cell的高度
在基本規(guī)則中可以看到,heightForRowAtIndexPath
方法會(huì)調(diào)用非常多的次數(shù),如果將高度計(jì)算放在方法中,那么可想而知,CPU會(huì)存在大量的消耗。所以,對(duì)于cell高度的計(jì)算,應(yīng)該在從網(wǎng)絡(luò)獲取到數(shù)據(jù)的時(shí)候就進(jìn)行計(jì)算,并且把計(jì)算的結(jié)果緩存起來。具體的做法,可以在數(shù)據(jù)模型model對(duì)象中添加一個(gè)cell高度的屬性,但是通常model類一般沒有實(shí)現(xiàn),就只有屬性,所以最好的方式是添加到viewModel中。
提前創(chuàng)建并緩存真正需要顯示的數(shù)據(jù)
有些從服務(wù)器中拿到的數(shù)據(jù),并不能用于視圖的顯示,這些數(shù)據(jù)需要做一些處理才能用于視圖顯示。同樣,我們可以在基本規(guī)則中看到,cellForRowAtIndexPath
也會(huì)執(zhí)行多次,所以這些處理不應(yīng)該直接放在該方法中。而應(yīng)該在從網(wǎng)絡(luò)獲取到數(shù)據(jù)的時(shí)候就進(jìn)行處理,同時(shí)緩存起來作為一個(gè)屬性。通常這也是MVVM模式中VM所做的操作之一。
按需加載cell
在滑動(dòng)的過程中,計(jì)算滾動(dòng)目標(biāo)范圍內(nèi)的cell進(jìn)行加載,而不加載滑動(dòng)過程中的cell,通過監(jiān)聽UIScrollView的代理方法來完成
避免使用透明圖層
設(shè)置圖層透明,系統(tǒng)會(huì)將透明圖層和下面的視圖進(jìn)行混合,而這種操作屬于渲染操作中很慢的操作
異步繪制
如果自定義cell的時(shí)候存在大量的子控件,那么這時(shí)候需要選擇使用異步繪制,來防止創(chuàng)建多個(gè)子對(duì)象,耗費(fèi)CPU資源。開啟子線程直接繪制元素而非創(chuàng)建對(duì)象。除此之外還可以通過重寫drawRect方法進(jìn)行元素的繪制,drawRect方法本身是異步的。