ScrollView:如何处理大量内容?

Har*_*rdy 5 swiftui

这段代码是对.NET的压力测试ScrollView。虽然ForEach包含3000个项目的循环渲染速度可以接受,但是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)
                }
            }
        })
    }
}
``
Run Code Online (Sandbox Code Playgroud)

yaw*_*eix 1

你为什么使用 aScrollview而不是 a List?AList将重用这些单元,这对于性能和内存管理来说要好得多。使用列表,当单元格滚动到看不见的地方时,它就会从视图中删除,这对性能有很大帮助。

有关性能差异的更多信息,请参阅此处

    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)
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

编辑:因为我错过了原来的问题,因为滚动视图是水平的。

一种选择是将 UICollectionView 包装到 UIViewRepresentable 中,请参阅此处的开发讨论,以及此处的示例实现,这将允许您将其显示为水平视图,同时获得列表的性能优势

  • 水平滚动 30,000 个项目是一个非常糟糕的主意。您应该考虑更改 UI 交互模型以更好地适应系统约定。 (3认同)