UITalbeView作為一個(gè)項(xiàng)目中常用的開發(fā)組件之一,如何讓其保持流暢的滑動(dòng)則是最重要的一個(gè)環(huán)節(jié)搀菩。
UITableView的核心思想為cell的重用機(jī)制。簡單的理解就是將滑出屏幕外的cell放進(jìn)重用池,當(dāng)要顯示某一位置的cell時(shí)绕辖,先去檢查重用池中是否有可重用的cell,如果有擂红,就直接拿來顯示仪际;如果沒有,才會(huì)創(chuàng)建昵骤。這樣做的好處可想而知树碱,極大的減少了內(nèi)存的開銷。
然而重用cell只是優(yōu)化UITableView的基礎(chǔ)变秦。
病因
App 主線程開始在 CPU 中計(jì)算顯示內(nèi)容成榜,比如視圖的創(chuàng)建、布局計(jì)算蹦玫、圖片解碼赎婚、文本繪制等。隨后 CPU 會(huì)將計(jì)算好的內(nèi)容提交到 GPU 去樱溉,由 GPU 進(jìn)行變換挣输、渲染等一系列的處理。隨后 GPU 會(huì)把渲染結(jié)果提交到幀緩沖區(qū)去福贞,等待顯示到屏幕上撩嚼。由于垂直同步的機(jī)制,如果一定的時(shí)間內(nèi)挖帘,CPU 或者 GPU 沒有完成內(nèi)容提交完丽,則那一幀就會(huì)被丟棄,等待下一次機(jī)會(huì)再顯示拇舀,而這時(shí)顯示屏?xí)A糁暗膬?nèi)容不變逻族。這就是界面卡頓的原因。
占用資源主要原因及解決方案
1你稚、控件的創(chuàng)建
在tableView中肯定有大量的內(nèi)容需要進(jìn)行展示瓷耙,所以在cell中肯定需要?jiǎng)?chuàng)建大量的UIView、UILabel之類的控件刁赖,在創(chuàng)建時(shí)就需要分配內(nèi)存搁痛、調(diào)整屬性,這些操作都是比較消耗CPU資源的宇弛。
在cellForRowAtIndexPath中不要出現(xiàn)創(chuàng)建對(duì)象的代碼鸡典,盡量在cell初始化的時(shí)候創(chuàng)建好所有的控件。盡量使用更為輕量的CALayer來代替UIView枪芒。
2彻况、視圖布局的計(jì)算
視圖布局的計(jì)算是吃CPU資源的主要原因之一谁尸,因?yàn)橛?jì)算,所以這方面的資源占用率就不可避免了纽甘。
雖然是不可避免的良蛮,但也需要將占用資源比例降低。
不論通過何種技術(shù)對(duì)視圖進(jìn)行布局悍赢,其最終都會(huì)落到對(duì) frame等屬性的調(diào)整上决瞳。對(duì)這些屬性的調(diào)整非常消耗資源,所以盡量提前計(jì)算好布局左权,在需要時(shí)一次性調(diào)整好對(duì)應(yīng)屬性皮胡,而不要頻繁的計(jì)算和調(diào)整這些屬性。
3赏迟、文本的計(jì)算
上面說了只要有計(jì)算屡贺,對(duì)資源的占用就不可避免,所以將文本寬高的計(jì)算放入子線程操作锌杀,會(huì)給主線程減少相當(dāng)一部分的空間甩栈。
4、圖像的繪制與圖形的生成
drawRect對(duì)資源的占用大家應(yīng)該都有所了解抛丽,因CoreGraphic 方法通常都是線程安全的谤职,所以圖像的繪制可以很容易的放到后臺(tái)線程進(jìn)行。
在項(xiàng)目中經(jīng)常會(huì)把頭像之類的控件設(shè)置成圓角亿鲜,如果我們操作CALayer的屬性通常都會(huì)觸發(fā)離屏渲染允蜈,而當(dāng)一個(gè)界面中出現(xiàn)大量的圓角圖像時(shí),滑動(dòng)幀率就會(huì)降得很低蒿柳。所以盡量避免使用CALayer來生成圓角屬性饶套。設(shè)置圓角可以參考:iOS 高效添加圓角效果實(shí)戰(zhàn)講解
優(yōu)化技巧
預(yù)排版
從后臺(tái)的回調(diào)中拿到數(shù)據(jù)時(shí),通過后臺(tái)線程將所有控件的高度與cell的整體高度都給計(jì)算出來垒探,然后將這些計(jì)算出來的高度都給緩存起來妓蛮。
高度返回
若高度一定,直接使用rowHeight屬性而不是使用heightForRowAtIndexPath方法圾叼,以減少調(diào)用的消耗蛤克。
圖片設(shè)置
在設(shè)置顯示圖片時(shí),不要直接設(shè)置UIImageView的contentMode屬性自動(dòng)適應(yīng)夷蚊,圖片變形會(huì)計(jì)算transform构挤,壓縮時(shí)會(huì)乘以一個(gè)矩陣,消耗性能惕鼓。對(duì)于要求性能較高的app筋现,應(yīng)該將得到的圖片經(jīng)過處理成UIImageView大小后再呈現(xiàn)。