iOS Swift UITableView的scrollToRow的"坑"

簡介

在tableView中,咱們通常會用到scrollToRow這個來控制tableView滾到指定的某一行。通常寫法以下所示swift

// MARK: 滾到底部
func scrollToBottom(animated: Bool = false) {
    if dataArr.count > 0 {
        tableView.scrollToRow(at: IndexPath(row: dataArr.count - 1, section: 0), at: .bottom, animated: animated)
    }
}
複製代碼

狀況

今天鄙人使用SnapKit來佈局cell,而後用scrollToRow來滾到底部就遇到了一個很奇葩的現象。 我設置了在鍵盤彈出後聊天消息列表會自動滾到底部。 1.隨便輸入一條消息,點發送後,在聊天消息列表中並無滾到最新消息那一行。 2.退出鍵盤不作任何操做再打開鍵盤也是滾到剛纔那裏(即最新消息的上一條所在位置) 3.只有在退出鍵盤後把聊天消息列表的消息向上拉一點距離露出最新消息所在的cell以後,再點擊纔有用 數組

分析

在無奈之下,通過了一步步的探索,終於發現了問題的所在 首先咱們要了解一下scrollToRow執行後會調用哪些函數及順序 會調用這兩個方法bash

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
複製代碼
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
複製代碼

步驟一

我在 heightForRow 中寫了具體的數據,也就是把高度寫死,再也不是動態獲取。接着執行程序獲得以下結果 好比我本來有10條數據,如今加入了一條後執行了scrollToRow,它會 1.先調用 heightForRow 11次,即包括最新加入的那一條 2.而後再調用 cellForRow 3.最後在調一次 heightForRow 後面的2和3是針對最新消息的微信

步驟二

我在 heightForRow 中再也不寫死高度,而是從模型數據中動態獲取高度(高度是在cell佈局後獲取的,再賦值到模型數據中的cellHeight變量)函數

執行程序獲得這個結果:調用 heightForRow 11次,而後就沒了
複製代碼

好吧,問題就出如今對heightForRow的第11次調用,前10次都有返回具體的高度,而最後一次是0~。佈局

結論

如今清楚了,要想在調用 scrollToRow 到指定的那一行,前提條件是那一行的高度不能爲0。 因此在上面的狀況中,發送完消息後,最新消息的cell的確是插入到了tableView,也有顯示出來(後面我本身測的),但就是沒法滾到最新消息那一行,就是由於 heightForRow 返回的高度爲0 在上面的狀況中,向上拉一點距離露出cell後scrollToRow纔有效就是由於此時heightForRow返回的高度再也不爲0ui

解決方案

按本人自身的狀況來講,有兩種解決方法spa

第一種

在傳入的模型數據中給予明確計算出來的數值就好。code

第二種

我使用SnapKit來自動佈局cell的位置而後再來獲取高度,這作法主要就是爲了不運算。因此我不選用第一種解決方法 好了,方法以下:cdn

// dataArr是用來存放模型的數組
let indexPath = IndexPath(row: dataArr.count - 1, section: 0)
// 調用tableView的數據源辦法
_ = self.tableView(tableView, cellForRowAt: indexPath)
複製代碼

在插入最新消息後,調用tableView的數據源方法來讓它先對cell進行佈局,這樣就獲取到了cell的高度,而後再執行 scrollToRow 就行了。

完美

微信公衆號
相關文章
相關標籤/搜索