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 条评论
登录 后参与评论

相关文章

来自专栏一个会写诗的程序员的博客

Spring Reactor 项目核心库Reactor Core

Non-Blocking Reactive Streams Foundation for the JVM both implementing a Reactiv...

2202
来自专栏张善友的专栏

LINQ via C# 系列文章

LINQ via C# Recently I am giving a series of talk on LINQ. the name “LINQ via C...

2665
来自专栏C#

DotNet加密方式解析--非对称加密

    新年新气象,也希望新年可以挣大钱。不管今年年底会不会跟去年一样,满怀抱负却又壮志未酬。(不过没事,我已为各位卜上一卦,卦象显示各位都能挣钱...)...

4938
来自专栏我和未来有约会

Silverlight第三方控件专题

这里我收集整理了目前网上silverlight第三方控件的专题,若果有所遗漏请告知我一下。 名称 简介 截图 telerik 商 RadC...

4045
来自专栏张善友的专栏

Silverlight + Model-View-ViewModel (MVVM)

     早在2005年,John Gossman写了一篇关于Model-View-ViewModel模式的博文,这种模式被他所在的微软的项目组用来创建Expr...

2998
来自专栏陈仁松博客

ASP.NET Core 'Microsoft.Win32.Registry' 错误修复

今天在发布Asp.net Core应用到Azure的时候出现错误InvalidOperationException: Cannot find compilati...

4878
来自专栏跟着阿笨一起玩NET

c#实现打印功能

2822
来自专栏张善友的专栏

Miguel de Icaza 细说 Mix 07大会上的Silverlight和DLR

Mono之父Miguel de Icaza 详细报道微软Mix 07大会上的Silverlight和DLR ,上面还谈到了Mono and Silverligh...

2717
来自专栏闻道于事

js登录滑动验证,不滑动无法登陆

js的判断这里是根据滑块的位置进行判断,应该是用一个flag判断 <%@ page language="java" contentType="text/html...

6998
来自专栏大内老A

The .NET of Tomorrow

Ed Charbeneau(http://developer.telerik.com/featured/the-net-of-tomorrow/) Exciti...

32110

扫码关注云+社区