【问题标题】:ScrollView: How to handle large amount of content?ScrollView:如何处理大量内容?
【发布时间】: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 来显示这么多的项目,因为它的性能很差。

标签: swiftui


【解决方案1】:

过去有一个技巧,可以让水平UITableView 现在用于反转填充(从下到上),您可以在这里使用它:

  • 使用垂直列表
  • 旋转 90˚
  • 将它的所有项目旋转-90˚

现在你有水平的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 而不是ListList 将重用单元,这对于性能和内存管理来说要好得多。当单元格滚动到视线之外时,列表会从视图中移除,这对性能有很大帮助。

    有关性能差异的更多信息,请参阅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 talkhere for an example implementation 这可以让您将其显示为水平视图,同时获得列表的性能优势

    【讨论】:

    • 好吧,我需要一个带有许多自定义内容的水平滚动条。我认为列表不足以满足我的用例。
    • 水平滚动浏览 30,000 个项目是一个非常糟糕的主意。您应该考虑更改您的 UI 交互模型以更好地适应系统约定。
    • 添加了水平滚动的细节
    • 我正在尝试优化模型,使其仅提供屏幕所需的项目。如何检索滚动位置以将其反馈给模型并相应地更新数据?
    • 我的情况有点不同,但我在外部ScrollView 的表现一直很差。我现在改用List,性能问题消失了。
    猜你喜欢
    • 1970-01-01
    • 2016-08-11
    • 2013-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多