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 就行了。

完美

微信公众号
相关文章
相关标签/搜索