作者:kirito_song
連結:https://www.jianshu.com/p/684d897be084
目錄
-
系統如何計算的自適應高度?
-
系統計算的行高會不會被快取?
-
如何快取?
前幾天讀檔案的時候發現一對方法
- (CGSize)systemLayoutSizeFittingSize:(CGSize)targetSize NS_AVAILABLE_IOS(6_0);
- (CGSize)systemLayoutSizeFittingSize:(CGSize)targetSize withHorizontalFittingPriority:(UILayoutPriority)horizontalFittingPriority verticalFittingPriority:(UILayoutPriority)verticalFittingPriority NS_AVAILABLE_IOS(8_0);
具體可以參閱《iOS檔案補完計劃–UIView》https://www.jianshu.com/p/ea3d2970a892中的相關解釋。
簡而言之這兩個方法會:
傳回Auto Layout後內容高度
並且、我們都知道UITableView、如果設定成rowHeight =
UITableViewAutomaticDimension的話。cell的高度將由系統透過Auto Layout自動計算。
系統如何計算的自適應高度?
而這個計算、是否透過上面兩個方法呢?
經過試驗、答案是肯定的。
系統呼叫的正是
– (CGSize)systemLayoutSizeFittingSize:(CGSize)targetSize withHorizontalFittingPriority:(UILayoutPriority)horizontalFittingPriority verticalFittingPriority:(UILayoutPriority)verticalFittingPriority NS_AVAILABLE_IOS(8_0);這個方法。
系統計算的行高會不會被快取?
經過試驗、答案是否定的。也就是系統不會快取計算過的行高
這裡有兩個能夠讓Cell自適應的方式
1、對UITableView進行設定
tableView.rowHeight = UITableViewAutomaticDimension
2、透過代理傳回
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return UITableViewAutomaticDimension;
}
結果是無論使用哪個方法、在每次Cell即將被展示的時候、都會自動呼叫上述的
systemLayoutSizeFittingSize方法。
兩個關鍵的步驟是:
1、透過cellForRowAtIndexPath對某個Cell進行配置
而我們在這一步已經將Cell的內容配置完畢了
2、透過[UITableView _heightForCell:atIndexPath:]計算Cell高度
而內部則呼叫systemLayoutSizeFittingSize獲取具體的高度。
如何快取?
經過以上兩個探索、我們已經知道Cell透過systemLayoutSizeFittingSize高度、並且不會被快取。
那麼、我們需要做的就是自己計算高度、並且快取。直接貼一下程式碼:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
BSQuestionsModel * model = _dataArray[indexPath.section];
return model.cell_height?:UITableViewAutomaticDimension;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
BSQuestionsModel * model = _dataArray[indexPath.section];
BSQuestionsTableViewCell * cell = [BSQuestionsTableViewCell cellForTableView:tableView model:model];
//高度快取
CGFloat height = [cell systemLayoutSizeFittingSize:CGSizeMake(tableView.frame.size.width, 0) withHorizontalFittingPriority:UILayoutPriorityRequired verticalFittingPriority:UILayoutPriorityFittingSizeLevel].height;
model.cell_height = height;
return cell;
}
這樣、cell在進行過一次高度計算之後。就不需要在計算第二次了
然後關於上面的程式碼有幾點需要說:
1、為什麼在cellForRowAtIndexPath裡做快取
最開始我們已經談過了、cellForRowAtIndexPath的呼叫在獲取自動佈局的高度之前、這樣也能避免重覆取用對應位置的Cell。
而傳回的UITableViewAutomaticDimension主要是為了怕低版本有問題(雖然我感覺應該不會)。
2、為什麼用
systemLayoutSizeFittingSize:withHorizontalFittingPriority:verticalFittingPriority
網上很多帖子都這樣寫:
[cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize]
但是在我這不太好用、因為我cell內部有一些優先順序的設定。
所以、我乾脆和系統呼叫的方式一樣。
3、非同步計算
是的、我們又可以非同步計算了。雖然我沒寫、因為我現在得抓緊碼頁面~
關於一些舊帖子
我搜到的都是14/15年的帖子、和現在的情況感覺還是有出入的。
1、cell.contentView取出的高度要+1
網上對+1的解釋是、cell比cell.contentView要搞出1個單位。還附上了兩張圖。
但是現在、cell是比cell.contentView高出0.5(0.5也不一定準確、xib上有四捨五入的嫌疑)、而不是1。
2、用cell還是用cell.contentView
我在網上搜了很多帖子、都說要使用cell.contentView
但是我用cell一樣可以獲取高度。所以用cell唄~
最後
本文主要是自己的學習與總結。如果文記憶體在紕漏、萬望留言斧正。如果願意補充以及不吝賜教小弟會更加感激。
●編號302,輸入編號直達本文
●輸入m獲取文章目錄
Web開發
更多推薦《18個技術類微信公眾號》
涵蓋:程式人生、演演算法與資料結構、駭客技術與網路安全、大資料技術、前端開發、Java、Python、Web開發、安卓開發、iOS開發、C/C++、.NET、Linux、資料庫、運維等。