滚动到 TableView 的最后一个元素需要太多时间

Posted

技术标签:

【中文标题】滚动到 TableView 的最后一个元素需要太多时间【英文标题】:Scroll to last element of TableView take too much time 【发布时间】:2017-01-02 07:25:59 【问题描述】:

我正在尝试模拟 Whatsapp 聊天,任何单元格都会有一个图像(对于气泡的尾部),一个只是带有颜色和一些角半径的视图的气泡以及一个代表消息文本的标签。

我在通话前后打印了一张照片

self.messagesTableView.reloadData()

一旦调用后打印,tableView 会持续一段时间,直到数据显示出来,我才知道是什么。在 indexpath 处插入行也是如此,显示插入动画需要一些时间。

func displayMessages(viewModel: GroupChatMessages.GetChatMessages.ViewModel) 
    let displayedMessage = viewModel.displayedMessages

    print ("i'm here!")

    messages = displayedMessage!

    //self.messagesTableView.performSelectorOnMainThread(Selector("reloadData"), withObject: nil, waitUntilDone: true)

    self.messagesTableView.reloadData()

    print ("i'm here2!")

    firstTime = false
    self.setVisible(hiddenTableView: false, hiddenChatLoader: true)
    self.scrollToLastMessage(false)
    self.messagesLoaded = true


我尝试使用队列进行调度,以及 reloadData() 之前的注释行,但没有任何效果,也没有任何代表有意义的时间。

也许是为了泡沫的形象?我不知道。我在 Assets 上保存了这张图片,所以我没有从互联网上下载它。

self.setVisible 只是隐藏加载器并显示 tableView 但我尝试过将其向上移动并且没有任何变化。如果您需要任何进一步的信息,请告诉我。谢谢!

编辑:

嗯,我已经看到问题出在滚动到最后一个单元格,这是它花费大部分时间的地方。

 func scrollToLastMessage(animated: Bool) 
    let section = 0
    let lastItemIndex = self.messagesTableView.numberOfRowsInSection(section) - 1
    let indexPath:NSIndexPath = NSIndexPath.init(forItem: lastItemIndex, inSection: section)
    self.messagesTableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Bottom, animated: animated)
    self.scrollDownButton.hidden = true

有一种优化滚动的可能性,因为我必须做一个滚动,因为一旦加载数据,我看到的第一行是 tableView 的顶行,但我想看到底部的(最后的)。谢谢!

【问题讨论】:

【参考方案1】:

reloadData() 之类的方法应该被视为 UI 方法,并且必须在主线程中调用它们:

DispatchQueue.main.async  tableView.reloadData() 

最好不要使用reloadData()函数,除非大量单元格需要刷新或数据源已更改,而是使用此方法添加新行:

tableView.insertRows(at: [IndexPath], with: UITableViewRowAnimation)

对于刷新单元格:

tableView.reloadRows(at: [IndexPath], with: UITableViewRowAnimation)

如果单元格有大量图像和渲染,请使用以下代码加快滚动速度:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath)
    // ADD THESE TWO LINE
    cell.layer.shouldRasterize = true
    cell.layer.rasterizationScale = UIScreen.main.scale

使用这些方式将显着提高加载速度

【讨论】:

Mousavian,感谢您现在插入了我正在使用 insertRows 的 reloadData,但问题仍然存在,因为我检测到问题来自滚动,如果您想检查,我更新了我的问题如果你知道如何解决这个问题。非常感谢你。 滚动一直有问题,花费了相同的时间。 你考虑重写cellForRowAt方法来加速加载使用DispatchQueue.async 将 cellForRowAt 的所有代码抓取到 DispatchQueue.async 中?稍后我会试试的,谢谢。 @Alex 没有,只​​有计算逻辑,UI 交互代码应该在主主线程中运行,你应该在调度块内调度到主队列【参考方案2】:

最后,我发现在等待滚动到最后一个元素时避免死亡的解决方案是交换表格的方向

tableView.transform = CGAffineTransformMakeRotation(-M_PI); cell.transform = CGAffineTransformMakeRotation(M_PI);

现在headerView 和footerView 颠倒了。例如,如果您想使用此配置在 TableView 底部(视觉上)插入行,您应该将其添加到位置 0 forRow: 0 atSection: "WhereYouAre"。这样当你添加新元素时,不需要滚动,因为滚动是自动的。恕我直言,惊人而奇怪的答案。

我在这里找到了这个解决方案:

Solution Link

@Christos Hadjikyriacou 在那里解决了。

【讨论】:

以上是关于滚动到 TableView 的最后一个元素需要太多时间的主要内容,如果未能解决你的问题,请参考以下文章

限制tableView中显示的单元格数量,滚动到最后一个单元格时加载更多单元格

当用户使用 UITableView 的后退按钮滚动到最后选定的行时

滚动时在最后一个 tableView 单元中添加按钮显示两次

Swift UISearchController tableview 搜索结果滚动不会在键盘上方移动到最后一行

如何滚动到 UITableView 或 UICollectionView 中的最后一个单元格之外

Tableview最后一个单元格使用滚动视图iOS不可见