我有非常大量数据的表格视图。 出于性能原因,无法一次性加载。 更多,有时应该加载数组的随机位置,因此增量分页不是一个好选择。
这些要求的当前解决方案是在数据阵列上滑动窗口。当用户滚动时,我从一端添加单元格并从另一端移除。我使用滚动位置(通过查看屏幕上的单元格)来确定是否有时间加载新数据。
通常,当您调用tableView.deleteRows(at:with:)
并从表的开头删除单元格时,tableView会调整其contentOffset
属性,以便用户仍然可以看到与操作前相同的单元格。
但是,当tableView在滚动后减速时,其contentOffset
在更新时不会调整,这会导致反复加载新页面直到减速完成。然后,在减速后的第一次更新中,contentOffset
由tableView修复并且加载停止。
向后滚动并使用tableView.insertRows(at:with:)
在表格的开头添加值时会发生同样的事情。
如何让UITableView正确调整其contentOffset?
还有其他方法可以克服这个错误 - 保持在数据数组中间加载任意部分并从中滚动的能力吗?
我做了一个小项目来说明这个错误:
答案 0 :(得分:2)
从您的示例项目中,我可以理解以下内容,
我检查了您的代码,您已经非常有趣地实施了sliding-window over data-source model
。由于您一直试图通过删除和读取单元格来有效地tableview
而导致的问题。
实际上,出列单元格应该重用已经在内存中的单元格。请看一下苹果文档,
出于性能原因,通常应该使用表视图的数据源 在将单元格分配给其中的行时,重用UITableViewCell对象 tableView(_:cellForRowAt :)方法。表视图维护队列或 数据源已标记的UITableViewCell对象的列表 重用。在被要求时,从您的数据源对象中调用此方法 为表视图提供一个新单元格。这种方法出了问题 现有单元格(如果有)或使用该类创建新单元格 或您之前注册的nib文件。如果没有可用的单元格 重用并且您没有注册类或nib文件,这种方法 返回nil。
好消息是,我删除了行删除和读取机制后,sliding-window over data-source model
工作正常。这是您的工作代码,
https://drive.google.com/file/d/0B2y_JJbzjRA6dDR3QzRMUzExSGs/view?usp=sharing
答案 1 :(得分:1)
从您的示例项目中,我可以理解您是否正在尝试通过窗口内容概念实现无限滚动,以便您始终可以拥有固定数量的行(索引路径,例如100),以便在窗口向下/向上滚动时 - 表视图相应地从顶部/底部删除indexPaths。 即使你有更多的数据源项,你总是可以拥有indexPaths的tableViews 100
基本上你在这里处理两个问题:
ContentOffset
动态高度
假设我们有高度固定(44)并且表没有反转。 要实现无限滚动窗口,您必须执行以下操作:
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
}
}
这样每次都会确定总内容大小
希望它会有所帮助。
修改: - 强> 这是修改后的代码,实际上在底部进行无限滚动 具有动态单元格高度的表视图。这不会使行数增加超过100.但仍会在滑动窗口中加载数据。 link