iOS - Swift UITableView的scrollToRow的"坑"

简介

在tableView中,我们一般会用到scrollToRow这个来控制tableView滚到指定的某一行。一般写法如下所示

// 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执行后会调用哪些函数及顺序 会调用这两个方法

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返回的高度不再为0

解决方案

按本人自身的情况来说,有两种解决方法

第一种

在传入的模型数据中给予明确计算出来的数值就好。

第二种

我使用SnapKit来自动布局cell的�位置然后再来获取高度,这做法主要就是为了避免运算。所以我不选用第一种解决方法 好了,方法如下:

// dataArr是用来存放模型的数组
let indexPath = IndexPath(row: dataArr.count - 1, section: 0)
// 调用tableView的数据源办法
_ = self.tableView(tableView, cellForRowAt: indexPath)

在插入�最新消息后,调用tableView的数据源�方法来让它先对cell进行布局,这样就获取到了cell的高度,然后再执行 scrollToRow 就好了。

�完美

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏对角另一面

读Zepto源码之Gesture模块

Gesture 模块基于 IOS 上的 Gesture 事件的封装,利用 scale 属性,封装出 pinch 系列事件。 读 Zepto 源码系列文章已经放到...

2310
来自专栏圣杰的专栏

ABP入门系列(14)——应用BootstrapTable表格插件

源码路径:Github-LearningMpaAbp 1. 引言 之前的文章ABP入门系列(7)——分页实现讲解了如何进行分页展示,但其分页展示仅适用于前台we...

5415
来自专栏林德熙的博客

C# 从零开始写 SharpDx 应用 初始化dx修改颜色

本文来告诉大家如何在上一篇博客创建的窗口里面使用 Sharpdx 初始化,然后设置窗口颜色。

1641
来自专栏落影的专栏

iOS开发笔记(六)

前言 专注、坚持,是优良的品格。 正文 1、cell和cell.contentView 的区别 在给UITableViewCell添加视图的时候,我们有以下两种...

3365
来自专栏小詹同学

人脸检测(二 )——MFC实现

一、关于MFC 微软基础类库(英语:Microsoft Foundation Classes,简称MFC)是一个微软公司提供的类库(class...

4556
来自专栏新工科课程建设探讨——以能源与动力工程专业为例

2.3.2 基于bootstrap框架写加法器

    什么是bootstrap?一套用js和CSS编写的框架模板,自己组装一下就可以编写比较美观的网页。官当介绍是组件库:

923
来自专栏宏伦工作室

解放你的双手,陪爸妈看春晚去!

1672
来自专栏高性能服务器开发

libevent源码深度剖析七 事件主循环

(1)libevent源码深度剖析一 序 (2)libevent源码深度剖析二 Reactor模式 (3)libevent源码深度剖析三 libevent基...

1084

使用Jekyll显示Jupyter笔记本

Jekyll是一个用Ruby编写的静态站点生成器,支持博客并与Github页面整合。因为Github只负责托管,这种设置使数据分析共享和可视化变得简单。Jeky...

792
来自专栏超然的博客

高效开发之SASS篇

作为通往前端大神之路的普通的一只学鸟,最近接触了一样稍微高逼格一点的神器,特与大家分享~

671

扫码关注云+社区