【问题标题】:Scroll to last element of TableView take too much time滚动到 TableView 的最后一个元素需要太多时间
【发布时间】: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 的顶行,但我想看到底部的(最后的)。谢谢!

【问题讨论】:

    标签: ios swift xcode uitableview


    【解决方案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 在那里解决了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-19
      • 2021-06-13
      • 2021-02-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多