滚动/分页时,UITableView无法正确处理contentOffset

TIM*_*MEX 10 uitableview uiscrollview ios

我有一个关于非常大量数据的表格视图.出于性能原因,无法一次性加载.更多,有时应该加载数组的随机位置,因此增量分页不是一个好选择.

当前这些要求的解决方案是在数据阵列上滑动窗口.当用户滚动时,我从一端添加单元格并从另一端移除.我使用滚动位置(通过查看屏幕上的单元格)来确定是否需要加载新数据.

通常,当您tableView.deleteRows(at:with:)从表的开头调用和删除单元格时,tableView会调整其contentOffset属性,以便用户仍然可以看到与操作前相同的单元格.

但是,当tableView在滚动后减速时,它contentOffset不会在更新时调整,这会导致反复加载新页面直到减速完成.然后,在减速后的第一次更新,contentOffset由tableView固定并加载停止.

当向后滚动并在表的开头添加值时,会发生同样的事情tableView.insertRows(at:with:).

如何让UITableView正确调整其contentOffset?

或者还有其他方法可以克服这个错误 - 保持在数据数组中间加载任意一块并从中滚动的能力?

我做了一个小项目来说明这个bug:

https://github.com/wsb9/TableViewExample

man*_*mku 2

从您的示例项目中,我可以理解您正在尝试通过窗口内容概念实现无限滚动,以便您始终可以拥有固定的行数(索引路径,假设为 100),以便当窗口向下/向上滚动时 - 表视图相应地从顶部/底部删除indexPaths。即使您有更多数据源项,您始终可以拥有 indexPaths 100 的 tableView

基本上你在这里处理两个问题:

  1. 内容偏移量

  2. 动态高度

假设高度是固定的 (44) 并且桌子没有倒置。要实现 Window 的无限滚动,您必须执行以下操作:

override func scrollViewDidScroll(_ scrollView: UIScrollView) {

        let bottom: CGFloat = scrollView.contentSize.height - scrollView.frame.size.height
        let buffer: CGFloat = 3 * 44
        let scrollPosition = scrollView.contentOffset.y

        if (scrollPosition > bottom - buffer) {
            dataSource.expose(dataSource.exposedRange.shift(by: 25))
            self.tableView.contentOffset.y -= self.dataSource.deltaHeightToRemove
        }
    }
Run Code Online (Sandbox Code Playgroud)
  • 决定滚动向下时需要保留多少高度缓冲区。此高度缓冲区是您决定向数据源中插入更多项目 (25) 后的高度。
  • 此时您必须从顶部删除项目
  • 当您从顶部删除项目时,您基本上是在告诉scrollView将其内容偏移量减少相同的高度。
  • 这样每次总内容大小都会固定

    希望它会有所帮助。

    编辑:- 这是修改后的代码,它实际上在表格视图底部以动态单元格高度进行无限滚动。这不会使行数增加超过 100,但仍会在滑动窗口中加载数据。 关联