在IOS開發(fā)中闷板,UITableView是最重要逗柴,最常用的控件之一蛹头。而對于UITableView的優(yōu)化,也是IOS開發(fā)程序員必須要思考的問題。剛好前段時間渣蜗,做的一個項目就碰到有關(guān)UITableView優(yōu)化屠尊,自己也找了很多資料,所以在這里整理一下我對tableView優(yōu)化的理解耕拷。
1.cell的重用
UITableView中最重要的就是cell的重用機制讼昆,只要是用了UITableView控件,就必定會涉及cell的重用骚烧。cell的重用機制:當tableView顯示的時候浸赫,只會創(chuàng)建在可視范圍的cell,為了使這些cell可以重用赃绊,cell在創(chuàng)建的時候會有一個重用標識 ReuseIdentifier既峡。當屏幕滾動時,有部分cell就會被移出屏幕碧查,這些cell會被放到一個緩存池中运敢,等待重用。當需要顯示一個cell的時候忠售,首先會到緩存池中查看有沒有對應的可重用的cell传惠,如果有,就直接拿來用稻扬,如果沒有涉枫,再去創(chuàng)建,這樣就會大大減少內(nèi)存的消耗腐螟。
override func viewDidLoad() {
super.viewDidLoad()
tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: ReuseIdentifier)
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(ReuseIdentifier, forIndexPath: indexPath)
return cell
}
2.緩存行高
在呈現(xiàn)cell之前愿汰,把cell的高度計算好緩存起來,避免每次加載cell的時候都要計算乐纸。對于高度的計算衬廷,還有個小細節(jié)需要注意汽绢,就是如果 row 的高度都一定吗跋,那就刪除代理中的這個 tableView:heightForRowAtIndexPath: 方法,設置 Table View 的 rowHeight 屬性宁昭。
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
//獲得模型
let model = models![indexPath.row]
//判斷模型里面之前有沒有緩存過行高
if model.rowHeight != nil {
return model.rowHeight!
}
//自己算行高:AutoLayout
//讓 cell自己對應內(nèi)容跌宛,直接獲取高度,這個cell不參與顯示
let cell = tableView.dequeueReusableCellWithIdentifier(ReuseIdentifier) as! CJStatusCell
cell.model = model
let heigth = cell.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height
//保存行高
model.rowHeight = heigth
return heigth
}
3.cellForRowAtIndexPath不要做耗時操作
主線程主要是用來顯示UI积仗,刷新界面的疆拘,為了不影響界面的流暢程度,耗時的操作都放到子線程去執(zhí)行寂曹。
4.盡量不要去添加和移除view, 先將會用到的控件懶加載,要就顯示,不要就隱藏哎迄。如果cell中有圖片控件回右,就使用異步加載圖片。
5.減少cell上subviews的數(shù)量
UITableViewCell包含了textLabel漱挚、detailTextLabel和imageView等翔烁,而你還可以自定義一些視圖放在它的contentView里。然而view是很大的對象旨涝,創(chuàng)建它會消耗較多資源蹬屹,并且也影響渲染的性能。
6.cell里面的控件,約束最好不要使用remake,動態(tài)添加約束是比較耗性能的
7.cell里面的控件,背景最好是不透明的 (圖層混合), view的背景顏色 clearColor盡量少
8.圖片圓角不要使用 layer.cornerRadius,圖層最好不要使用陰影, 陰影會導致離屏渲染
9.異步繪制
我在這邊寫了一個UIImage的分類白华,是用來異步繪制哩治。
import UIKit
extension UIImage {
func cj_AsyncDrawImage(var size: CGSize?, bgColor: UIColor? = UIColor.whiteColor(), isCorner: Bool = false, drawFinish: (image: UIImage)->()) {
let start = CACurrentMediaTime()
if size == nil {
//別人沒有傳入size
size = self.size
}
//上下文大小為rect
let rect = CGRect(origin: CGPointZero, size: size!)
//開啟上下文
UIGraphicsBeginImageContextWithOptions(size!, bgColor != nil, UIScreen.mainScreen().scale)
//設置背景顏色
bgColor?.setFill()
UIRectFill(rect)
//需要圓角
if isCorner {
//路徑
let path = UIBezierPath(ovalInRect: rect)
//讓后面繪制的元素在路徑里面
path.addClip()
}
self.drawInRect(rect)
//獲取圖片
let newImage = UIGraphicsGetImageFromCurrentImageContext()
//結(jié)束上下文
UIGraphicsEndImageContext()
let end = CACurrentMediaTime()
// CJPrint("異步繪制時間:\(end - start)")
//返回繪制好的圖片
dispatch_async(dispatch_get_global_queue(0, 0)) { () -> Void in
drawFinish(image: newImage)
}
}
}