调用reloadData后,UITableView动态单元格高度滚动到顶部

时间:2017-05-22 11:53:21

标签: ios swift uitableview

我的tableView

中有动态单元格高度
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 100

我想和whatsapp app(分页)做同样的事情,我想加载25乘25行,所以当用户在顶部滚动时,我想加载新数据但我想保持相同的滚动位置,这里是我的意思确实

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    if isMore && scrollView.contentOffset.y == 0 {
         loadMore() // function that add new data in my model
         self.tableView.reloadData()
    }
} 

我遇到的问题是在我到达我的tableview顶部后调用reloadData但是tableView滚动到UP

我测试了其他类似的解决方案:

var cellHeights: [IndexPath : CGFloat] = [:]

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    cellHeights[indexPath] = cell.frame.size.height
}

func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
    guard let height = cellHeights[indexPath] else { return 70.0 }
    return height
}   

但仍然无法正常工作

3 个答案:

答案 0 :(得分:0)

如果要重新加载表以添加更多数据,那么在重新加载调用下面的函数后保留滚动位置。

tableview.scrollToRow(at: indexPath, at: .middle, animated: true)

这里indexPath是重载前最后一个单元格的indexPath。

答案 1 :(得分:0)

tableView:cellForRowAt中,当您检测到indexPath接近最后一个元素时(indexPath.row接近yourArray.count时),请查询更多项目。如果有它们,请将它们添加到数据源(数组或其他任何内容,表中包含所有对象)并重新加载表视图。表视图应显示新项目,用户可以继续滚动而不做任何特殊操作。

您不应该等到最后一个单元格调用tableView:cellForRowAt,因为如果您需要调用服务器来获取更多项目,则用户必须等待。 Whatsapp的滚动很快,因为他们在你滚动到最后一个元素之前很好地下载了这些项目(前一段时间它确实停止了,但现在他们可能更早地获取新项目)。

请记住,25个项目可能太少,网络速度慢,用户可能会滚动浏览您要显示的更多项目之前的项目,并且必须等待,这不是一个好的用户体验。模拟慢速网络连接,看看当您的应用与服务器联系时,25个项目是否足以滚动(取决于网络速度,请求和响应大小,服务器响应请求的速度等)。

答案 2 :(得分:0)

我在消息传递应用程序中遇到了同样的问题。这就是我解决它的方法:

  1. 为数据源阵列中的每个消息分配了唯一的messageId

  2. cellForRow:中,我保存了名为messageId的变量中第一行的messageIdFirst

    if(indexPath.row == 0){
        messageIdFirst = message.id!
    }
    
  3. loadMore()方法中,我检查当前 indexpath 行在当前更新的数据源数组中是否具有相同的 messageId

    if(message.id == messageIdFirst){
        previousTopIndexPath = i
    }
    

    ,其中i是数据源数组中具有相同messageId.

  4. 的索引
  5. 现在,我滚动到previousTopIndexPath,就像这样:

    tableview.scrollToRow(at: previousTopIndexPath, at: .middle, animated: true)

  6. 注1 :由于这在UITableView中效率不高,我最终使用UICollectionView使用相同的解决方案。

    注2:虽然这确实很顺利,但我知道必须有更清洁的方法来实现这一目标。