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 现在用于反转填充(从下到上),您可以在这里使用它:

使用垂直列表 旋转 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 talk 和 here for an example implementation 这可以让您将其显示为水平视图,同时获得列表的性能优势

【讨论】:

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

以上是关于ScrollView:如何处理大量内容?的主要内容,如果未能解决你的问题,请参考以下文章

你如何处理大量的小文件?

实体框架如何处理大量记录? [关闭]

如何处理来自 REST 服务的大量数据

使用 Haskell,我如何处理大量的 XML?

如何处理 MongoDB 中大量的群聊消息?

Show proceslist时发现大量的sleep,有啥风险吗,该如何处理?