ScrollView:如何处理大量内容?
Posted
技术标签:
【中文标题】ScrollView:如何处理大量内容?【英文标题】:ScrollView: How to handle large amount of content? 【发布时间】:2019-08-04 10:18:21 【问题描述】:这段代码是对ScrollView
的一种压力测试。虽然包含 3000 个项目的 ForEach
循环渲染速度可以接受,但 30000 需要很长时间,并且 300000 永远(我在 3 分钟后停止)。
但是,在某些情况下,您需要滚动很多内容,想象一下具有可缩放比例(十年/年/月/日)的时间线。在这种情况下,可能有 50 年的天数要显示,用户必须有机会放大和缩小才能更改比例。
因此,我的问题是:SwiftUI 可以使用哪些策略来优化缓存、预取等,或者找出用户滚动后接下来要显示的部分,并防止模型计算宽度?
更准确地说:模型知道要显示的所有数据。 ScrollView
必须提供一个内容视图,该视图具有要显示的所有项目的宽度。这个宽度是我的问题:如何在没有所有项目可用的情况下以一种有意义的方式确定它?
struct TestScrollView: View
var body: some View
ScrollView(.horizontal, showsIndicators: true, content:
HStack(alignment: .bottom, spacing: 1)
// 3000 is working, 30000 not well, 300000 takes forever:
ForEach(1 ..< 30000) index in
Rectangle()
.fill(Color.yellow)
.frame(minWidth: 100, idealWidth: 200, maxWidth: 300, minHeight: 500, idealHeight: 500, maxHeight: 500, alignment: .bottom)
)
``
【问题讨论】:
顺便说一句,在我的项目中,显示大约 2000 个项目的列表是可以的。但是,当我对项目应用过滤器时,例如,保留 1000 个项目,重新渲染列表需要花费大量时间,似乎计算每个单元格是否应该保留是耗时的。所以我认为现在甚至不适合使用 List 来显示这么多的项目,因为它的性能很差。 【参考方案1】:过去有一个技巧,可以让水平UITableView
现在用于反转填充(从下到上),您可以在这里使用它:
现在你有水平的List
struct ContentView: View
var body: some View
List
ForEach(1 ..< 30000) index in
Text("\(index)")
.rotationEffect(.init(degrees: -90))
.rotationEffect(.init(degrees: 90))
.position(x: 10, y: 200) // Set to correct offset
【讨论】:
【参考方案2】:您为什么使用Scrollview
而不是List
? List
将重用单元,这对于性能和内存管理来说要好得多。当单元格滚动到视线之外时,列表会从视图中移除,这对性能有很大帮助。
有关性能差异的更多信息,请参阅here
var body: some View
List
ForEach(1..< 30000)
index in
Rectangle()
.fill(Color.yellow)
.frame(minWidth: 100, idealWidth: 200, maxWidth: 300, minHeight: 500, idealHeight: 500, maxHeight: 500, alignment: .bottom)
编辑:因为滚动视图是水平的,所以我错过了原始问题。
一种选择是将 UICollectionView 包装到 UIViewRepresentable 中,请参阅 here for the dev talk 和 here for an example implementation 这可以让您将其显示为水平视图,同时获得列表的性能优势
【讨论】:
好吧,我需要一个带有许多自定义内容的水平滚动条。我认为列表不足以满足我的用例。 水平滚动浏览 30,000 个项目是一个非常糟糕的主意。您应该考虑更改您的 UI 交互模型以更好地适应系统约定。 添加了水平滚动的细节 我正在尝试优化模型,使其仅提供屏幕所需的项目。如何检索滚动位置以将其反馈给模型并相应地更新数据? 我的情况有点不同,但我在外部ScrollView
的表现一直很差。我现在改用List
,性能问题消失了。以上是关于ScrollView:如何处理大量内容?的主要内容,如果未能解决你的问题,请参考以下文章