歡迎光臨
每天分享高質量文章

iOS-談一談自適應acCell的高度快取

作者: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、資料庫、運維等。

贊(0)

分享創造快樂