UITableView的優(yōu)化

最近看到有些面試題中會(huì)問(wèn)到TableView的優(yōu)化境蔼,特定花了幾天時(shí)間研究了一下各種優(yōu)化技巧灶平,主要就分為幾個(gè)主要方向:

  • 從重用Cell的方面去優(yōu)化
  • 從圖層屬性箍土,圓角/陰影等方面去優(yōu)化
  • 從UIView的繪制方面去優(yōu)化
  • 從預(yù)計(jì)算和緩存高度逢享,按需加載的方面去優(yōu)化

從一個(gè)初學(xué)者寫(xiě)的卡到爆的TableView例子說(shuō)起(引用自這里)

  • (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    ContacterTableCell *cell = [tableView dequeueReusableCellWithIdentifier:@"ContacterTableCell"];
    if (!cell) {
    cell = (ContacterTableCell *)[[[NSBundle mainBundle] loadNibNamed:@"ContacterTableCell" owner:self options:nil] lastObject];
    }
    NSDictionary *dict = self.dataList[indexPath.row];
    [cell setContentInfo:dict];
    return cell;
    }
如果沒(méi)有在xib中設(shè)置重用的標(biāo)識(shí),上面的cell就不會(huì)發(fā)生重用吴藻,只要TableView發(fā)生滾動(dòng)瞒爬,cellForRowAtIndexPath就會(huì)被調(diào)用,每一次cellForRowAtIndexPath被調(diào)用都會(huì)從NSBundle中獲取View的示例再賦給cell沟堡。眾所周知從NSBundle中讀取數(shù)據(jù)是非常的慢的侧但,所以這樣寫(xiě)出的代碼必定會(huì)卡到爆(我當(dāng)初剛學(xué)iOS的時(shí)候就是這樣寫(xiě)的(-_-))。

## 既然卡到爆就重用啰
首先注冊(cè)cell

    table = UITableView(frame: self.view.bounds, style: UITableViewStyle.Plain)
    table?.registerClass(UITableViewCell.self, forCellReuseIdentifier: "mainViewControllerCellId")

然后重用

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("mainViewControllerCellId")
    // config cell data
    cell?.textLabel?.text = titles[indexPath.row]
    cell?.selectionStyle = .None
    return cell!
}
可以看到航罗,使用了基本的重用機(jī)制后,整個(gè)TableView就變得流暢起來(lái)了粥血,而且按照這種做法燕侠,cell的生產(chǎn)和使用就分開(kāi)了立莉,cellForRowAtIndexPath就只專注于設(shè)置cell的數(shù)據(jù),不關(guān)心cell的初始化七问。一般的TableView界面采用這種寫(xiě)法都能獲得不錯(cuò)的性能,而且有一定經(jīng)驗(yàn)的iOS老手都是這樣寫(xiě)的械巡。

## 萬(wàn)一Cell中有圓角蒙版陰影透明這些圖層屬性呢
在UIView中刹淌,透明效果的渲染讥耗,圓角的渲染有勾,蒙版的渲染,陰影的渲染會(huì)消耗很大部分的性能古程。在靜態(tài)的View之中,這部分只消耗一次挣磨,不會(huì)造成太大的影響雇逞,但是在想U(xiǎn)ITableViewCell這些重用的動(dòng)態(tài)的View中,每一次的重用都會(huì)消耗一次塘砸,所以總的性能消耗會(huì)很大。當(dāng)然晤锥,要想在cell中使用這些屬性廊宪,還是有優(yōu)化的技巧來(lái)減少性能的消耗的。

#### 首先女轿,盡量減少透明View箭启。
UIView有一個(gè)屬性```opaque ```谈喳,當(dāng)不需要透明時(shí)可以將其設(shè)置為true册烈,這樣可以減少性能消耗。

#### 其次婿禽,減少離屏渲染
通常圖層的以下屬性將會(huì)觸發(fā)離屏渲染:
* 陰影(UIView.layer.shadowOffset/shadowRadius/...)
* 圓角(當(dāng) UIView.layer.cornerRadius 和 UIView.layer.maskToBounds 一起使用時(shí))
* 圖層蒙板

對(duì)于以上這些,要減少離屏渲染比較好的方法是使用shadowPath來(lái)設(shè)置陰影扭倾,使用裁剪過(guò)的圖片代替圓角而不是使用cornerRadius淀零,圖層模板能不用就不用膛壹。

#### 最后驾中,合理使用光柵化
當(dāng)然,除了第二點(diǎn)減少離屏渲染外肩民,還有一點(diǎn)就是要合理使用光柵化。使用光柵化能夠?qū)⒛軌蛴行岣咝阅芰捶剑琜把layer的shouldRasterize設(shè)為YES后,CALayer會(huì)被光柵化為bitmap祟蚀,layer的陰影等效果也會(huì)被保存到bitmap中作為緩存工窍。在使用了shadow或cornerRadius等效果時(shí),緩存使性能得到提升](http://zhijiang.me/2015/08/03/%E5%BD%B1%E5%93%8D%E5%9B%BE%E5%BD%A2%E6%80%A7%E8%83%BD%E7%9A%84%E5%9B%A0%E7%B4%A0%E5%92%8C%E4%BD%BF%E7%94%A8Instrument%E8%BF%9B%E8%A1%8C%E6%A3%80%E6%B5%8B/)患雏。

但是,使用光柵化要注意幾點(diǎn):

- 更新已經(jīng)光柵化的CALayer會(huì)造成離屏渲染 (這最重要)
- 被光柵化的bitmap如果超過(guò)100ms沒(méi)有被使用則會(huì)被移除
- 系統(tǒng)限制緩存的大小為2.5 x screen size

對(duì)于經(jīng)常改動(dòng)的罢维,不易采用光柵化,否則會(huì)增加離屏渲染肺孵,增加性能消耗攻人。對(duì)于相對(duì)靜態(tài)的入客,建議采用光柵化。特別是界面比較復(fù)雜给赞,動(dòng)畫(huà)比較復(fù)雜的初婆,都建議使用光柵化蓬坡。

## 糟糕我遇到了很復(fù)雜的Cell
由于繪制渲染復(fù)雜View的過(guò)程是非常耗時(shí)的猿棉,有時(shí)真的不排除遇到很復(fù)雜CellView的情況。由于本人對(duì)Core Graphics不太熟練屑咳,而且最近有點(diǎn)小忙,所以就不提供代碼兆龙,只提供一些優(yōu)化思路杖爽。
核心優(yōu)化就兩點(diǎn):

1. 使用Core Graphics進(jìn)行重繪紫皇,更進(jìn)一步就是將所有subViews繪制成一張圖片慰安,通過(guò)消除View樹(shù)的層級(jí)來(lái)提高效率。通俗來(lái)說(shuō)就是所謂的扁平化化焕。。铃剔。
通過(guò)重繪來(lái)壓縮View樹(shù)層級(jí),能大大提高View的繪制效率键兜,特別對(duì)于一些復(fù)雜界面效果特別明顯凤类。當(dāng)然缺點(diǎn)就是使用重繪比較復(fù)雜,開(kāi)發(fā)一些相對(duì)簡(jiǎn)單的界面可能會(huì)影響開(kāi)發(fā)效率踱蠢。

2.異步繪制渲染。
這個(gè)就是將View的繪制渲染放到后臺(tái)線程中棋电,完成后再通知主線程更新UI。這個(gè)思路跟Facebook的一個(gè)非常出名的開(kāi)源框架[AsyncDisplayKit](https://github.com/facebook/AsyncDisplayKit)類似苇侵。

## 我想我的TableView更動(dòng)人
如何更進(jìn)一步優(yōu)化TableView的體驗(yàn)赶盔?答案就是就兩點(diǎn):
- cell高度緩存和預(yù)計(jì)算
- 按需加載

對(duì)于第一點(diǎn)cell高度緩存和預(yù)計(jì)算榆浓,簡(jiǎn)單來(lái)說(shuō)就是計(jì)算每一個(gè)cell的高度并緩存起來(lái)于未,避免重復(fù)計(jì)算陡鹃。這里有個(gè)更合理的方法是[在用戶不滑動(dòng)TableView時(shí)烘浦,通過(guò)監(jiān)聽(tīng)runloop來(lái)啟動(dòng)后臺(tái)cell高度計(jì)算和緩存](http://blog.sunnyxx.com/2015/05/17/cell-height-calculation/)。這樣做的好處時(shí)將用戶交互和耗時(shí)計(jì)算任務(wù)進(jìn)行合理的分時(shí)闷叉,既不影響用戶交互,也不浪費(fèi)CPU計(jì)算性能脊阴。

對(duì)于第二點(diǎn)蚯瞧,用戶滾動(dòng)TableView的時(shí)候,希望能盡快看到當(dāng)前屏幕顯示的內(nèi)容品擎,而不關(guān)心其他還沒(méi)有滾動(dòng)到當(dāng)前屏幕的內(nèi)容埋合。所以萄传,一個(gè)比較有效的優(yōu)化思路是優(yōu)先繪制加載當(dāng)前的內(nèi)容甚颂,暫時(shí)忽略其他內(nèi)容。根據(jù)這個(gè)思路秀菱,可以使用UIScrollView的協(xié)議方法振诬,監(jiān)聽(tīng)滾動(dòng)的offset,然后當(dāng)用戶暫停滾動(dòng)時(shí)的屏幕贷揽,就是需要優(yōu)先加載的屏幕內(nèi)容,這時(shí)候可以再去加載當(dāng)前內(nèi)容梦碗,而不是一開(kāi)始按照滾動(dòng)順序全部加載。這樣的話就不用特地設(shè)置一個(gè)網(wǎng)絡(luò)請(qǐng)求的隊(duì)列來(lái)管理網(wǎng)絡(luò)請(qǐng)求洪规,而且發(fā)出去了的請(qǐng)求也是cancel不了的印屁。


## 總結(jié)
感覺(jué)對(duì)TableView的優(yōu)化有了點(diǎn)思路斩例,但是優(yōu)化方法太多以至于還沒(méi)消化過(guò)來(lái)雄人,但是大的優(yōu)化方向也是很清晰的:

- 能重用就重用
- 盡量減少view層級(jí)
- 使用異步繪制
- 使用緩存
- 按需加載
- 對(duì)于某些layer屬性盡量采用替代方案

總之,這幾天對(duì)這個(gè)專題的研究础钠,收獲很多,特定分享出來(lái)叉谜,寫(xiě)的不好旗吁,還望指教停局。

## 參考

[優(yōu)化UITableViewCell高度計(jì)算的那些事](http://blog.sunnyxx.com/2015/05/17/cell-height-calculation/)

[[iOS 程序性能優(yōu)化](http://www.samirchen.com/ios-performance-optimization)](http://www.samirchen.com/ios-performance-optimization/)

[UITableView優(yōu)化技巧](http://longxdragon.github.io/2015/05/26/UITableView%E4%BC%98%E5%8C%96%E6%8A%80%E5%B7%A7/)

[如何加強(qiáng) iOS 里的列表滾動(dòng)時(shí)的順暢感很钓?](http://www.zhihu.com/question/20382396)

[影響圖形性能的因素和使用Instrument進(jìn)行檢測(cè)](http://zhijiang.me/2015/08/03/%E5%BD%B1%E5%93%8D%E5%9B%BE%E5%BD%A2%E6%80%A7%E8%83%BD%E7%9A%84%E5%9B%A0%E7%B4%A0%E5%92%8C%E4%BD%BF%E7%94%A8Instrument%E8%BF%9B%E8%A1%8C%E6%A3%80%E6%B5%8B/)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市董栽,隨后出現(xiàn)的幾起案子码倦,更是在濱河造成了極大的恐慌锭碳,老刑警劉巖袁稽,帶你破解...
    沈念sama閱讀 217,509評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件擒抛,死亡現(xiàn)場(chǎng)離奇詭異运提,居然都是意外死亡蝗柔,警方通過(guò)查閱死者的電腦和手機(jī)民泵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)癣丧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)栈妆,“玉大人胁编,你說(shuō)我怎么就攤上這事℃页龋” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,875評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵寥假,是天一觀的道長(zhǎng)市框。 經(jīng)常有香客問(wèn)我,道長(zhǎng)糕韧,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,441評(píng)論 1 293
  • 正文 為了忘掉前任萤彩,我火速辦了婚禮,結(jié)果婚禮上雀扶,老公的妹妹穿的比我還像新娘杖小。我一直安慰自己,他們只是感情好予权,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著浪册,像睡著了一般。 火紅的嫁衣襯著肌膚如雪议经。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,365評(píng)論 1 302
  • 那天煞肾,我揣著相機(jī)與錄音,去河邊找鬼嗓袱。 笑死籍救,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的渠抹。 我是一名探鬼主播闪萄,決...
    沈念sama閱讀 40,190評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼奇颠!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起烈拒,我...
    開(kāi)封第一講書(shū)人閱讀 39,062評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎荆几,沒(méi)想到半個(gè)月后吓妆,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,500評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡行拢,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評(píng)論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了舟奠。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,834評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡狐胎,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出握巢,到底是詐尸還是另有隱情晕鹊,我是刑警寧澤暴浦,帶...
    沈念sama閱讀 35,559評(píng)論 5 345
  • 正文 年R本政府宣布溅话,位于F島的核電站,受9級(jí)特大地震影響飞几,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜独撇,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望纷铣。 院中可真熱鬧卵史,春花似錦、人聲如沸以躯。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,779評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)刁标。三九已至,卻和暖如春址晕,著一層夾襖步出監(jiān)牢的瞬間膀懈,已是汗流浹背斩箫。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,912評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工吏砂, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留乘客,地道東北人狐血。 一個(gè)月前我還...
    沈念sama閱讀 47,958評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像匈织,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子牡直,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 背景 UITableView作為iOS開(kāi)發(fā)中最重要和常用的控件之一,其中的實(shí)現(xiàn)原理值得深入研究一下。蘋(píng)果軟件在這塊...
    瘋狂的Cracker閱讀 712評(píng)論 2 4
  • 1. a.將cell及它的子控件設(shè)置為不透明的碰逸。b.盡量少用或不用透明圖層乡小。c.減少子控件的數(shù)量饵史。d.盡量少用ad...
    BEYOND黃閱讀 1,129評(píng)論 0 7
  • 簡(jiǎn)單的介紹 UITableView最核心的思想就是UITableViewCell的重用機(jī)制满钟。簡(jiǎn)單的理解就是:UIT...
    面包與世界閱讀 176評(píng)論 0 0
  • 9980r閱讀 121評(píng)論 0 0
  • 目標(biāo):百分之九十以上的分?jǐn)?shù) 第二天看書(shū)補(bǔ)完 中心詞:實(shí)習(xí) 其實(shí)我才發(fā)現(xiàn)園藝胳喷,并不是農(nóng)學(xué)湃番。 園藝只是后花園的藝術(shù) 并...
    良辰美LiangChen閱讀 229評(píng)論 0 0