iOS-談一談自適應Cell的高度緩存

目錄

  • 系統如何計算的自適應高度?
  • 系統計算的行高會不會被緩存?
  • 如何緩存?

前幾天讀文檔的時候發現一對方法

- (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》中的相關解釋。

簡而言之這兩個方法會:

返回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
  1. 通過代理返回
- (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主要是爲了怕低版本有問題(雖然我感覺應該不會)。

  1. 爲什麼用systemLayoutSizeFittingSize:withHorizontalFittingPriority:verticalFittingPriority
    網上很多帖子都這樣寫:
[cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize]

但是在我這不太好用、因爲我cell內部有一些優先級的設置。

所以、我乾脆和系統調用的方式一樣。

  1. 異步計算
    是的、我們又可以異步計算了。雖然我沒寫、因爲我現在得抓緊碼頁面~
關於一些舊帖子

我搜到的都是14/15年的帖子、和現在的情況感覺還是有出入的。

  1. cell.contentView取出的高度要+1
    網上對+1的解釋是、cellcell.contentView要搞出1個單位。還附上了兩張圖。

但是現在、cell是比cell.contentView高出0.5(0.5也不一定準確、xib上有四捨五入的嫌疑)、而不是1。

  1. cell還是用cell.contentView
    我在網上搜了很多帖子、都說要使用cell.contentView
    但是我用cell一樣可以獲取高度。所以用cell唄~

最後

本文主要是自己的學習與總結。如果文內存在紕漏、萬望留言斧正。如果願意補充以及不吝賜教小弟會更加感激。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章