作為一個android開發(fā)移民,在知曉UITableView可能會計算每一個cell的高度時,心里面還是驚了一下。Android的開發(fā)文檔中,不會有關于計算高度這方面的內(nèi)容,數(shù)據(jù)的多少和排版決定高度數(shù)值的大小不假,但去“感知”自己的高度難道不是ui組件分內(nèi)的事兒嗎?
可惜這種疑問并沒有支撐多久,因為大腦的另一側(cè)已經(jīng)出現(xiàn)android自適應高度時各種坑和bug,比如在ScrollView當中創(chuàng)建ListView,會發(fā)現(xiàn)設置成為自適應高度、多行數(shù)據(jù)的ListView變成細細一杠,讓每一個新手開發(fā)大腦回旋“What the fu*k”,用手指撥動它還會上下滑動,像極了LED。至少就動態(tài)計算列表高度這一點上,ios和android都沒長出什么甜果子。
好了,我只需要知道,一個展示大量列表數(shù)據(jù)的滑動組件想知道自己的高度,就得計算各個子view的高度,即UITableView需要知道每一個UITableViewCell的高度,這樣一來,就算是每個UITableViewCell的高度大小不一,也能完美顯示。

那么如何計算每一個UITableViewCell的高度呢?很簡單,分兩步:
- 用systemLayoutSizeFittingSize:UILayoutFittingCompressedSize獲取高度。
- 在heightForRowAtIndexPath當中返回這個高度。
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if(cell != nil) {
let size: CGSize = (cell?.contentView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize))!
return (size.height + 1)
}
return 0
}
需要解釋的地方在于這個“return (size.height+1)”,為什么要加1?因為這里獲取的size是cell當中contentView的size,cell作為老子肯定要比兒子高一頭啦,不然怎么管得住兒子?
Cell = ContentView(size.height) + Separator(1px)
利用systemLayoutSizeFittingSize獲取cell中contentView的size還有一個前提,就是contentView需要設定constraints,所以實際上這是一個與Auto Layout配套的高度獲取方式。

為每個cell計算高度再相加會得到整個UITableView的高度,問題也在于每個cell的計算過程會耗費時間,有大量cell的時候會使得整個ui展示的效率不高,怎么辦呢?
這里有一個聰明的概念上的劃分,就是“能夠被用戶看見的cell”和“用戶還沒有看見的cell”。這里可能有上千行數(shù)據(jù),作為系統(tǒng)而言,它計算了每個cell的高度,但是手機屏幕高度有限,只看得到幾個cell,這種大量的計算不是很浪費么?就好比我是一家生意紅火餐館,能坐200桌客人,吃飯高峰期我們家客滿了,還會在門外等50桌客人,我有必要為這等待的50桌客人備好菜么?我只需要知道等待的這50桌人大概會吃多少菜,保證廚房中的原料足夠就可以了。UITableView也有這么一個功能,給還沒有看見的cell一個估計的高度,這樣既能知道自己的高度大概是多少,又不造成浪費,提高效率。
override func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 78
}