SwiftUI ScrollView 没有更新?

Posted

技术标签:

【中文标题】SwiftUI ScrollView 没有更新?【英文标题】:SwiftUI ScrollView not getting updated? 【发布时间】:2019-11-13 05:35:54 【问题描述】:

目标

获取要在scrollView中显示的数据

预期结果

实际结果

替代方案

使用List,但不够灵活(不能去掉分隔符,不能多列)

代码

struct Object: Identifiable 
    var id: String


struct Test: View 
    @State var array = [Object]()

    var body: some View 
//        return VStack  // uncomment this to see that it works perfectly fine
        return ScrollView(.vertical) 
            ForEach(array)  o in
                Text(o.id)
            
        
        .onAppear(perform: 
            self.array = [Object(id: "1"),Object(id: "2"),Object(id: "3"),Object(id: "4"),Object(id: "5")]
        )
    

【问题讨论】:

我在 Xcode 11.1、ios 13.1、Swift 5 上对此进行了测试,得到了预期的结果(尽管滚动视图位于顶部而不是中心)。 你也不需要关键字return 有趣,我正在使用 Xcode 11.2、iOS 13.2、Swift 5 是的,我之前有一个print 声明,因此return 我使用此代码向 Apple 提交了 FB8101550。感谢您记录此错误并制作一个小型复制案例。后代:github.com/jgale/SwiftUIScrollViewUpdateBug 【参考方案1】:

解决这个问题的一个不那么老套的方法是将 ScrollView 包含在一个 IF 语句中,以检查数组是否为空

if !self.array.isEmpty
     ScrollView(.vertical) 
          ForEach(array)  o in
               Text(o.id)
          
     

【讨论】:

【参考方案2】:

我发现如果状态初始化为某个值而不是空数组,它可以按预期工作(Xcode 11.2)。在这种情况下,更新工作正常,初始状态无效。

struct TestScrollViewOnAppear: View 
    @State var array = [Object(id: "1")]

    var body: some View 
        ScrollView(.vertical) 
            ForEach(array)  o in
                Text(o.id)
            
        
        .onAppear(perform: 
            self.array = [Object(id: "1"),Object(id: "2"),Object(id: "3"),Object(id: "4"),Object(id: "5")]
        )
    

【讨论】:

适用于简单情况,在我的情况下,我在onAppear 有一个网络调用,因此使用虚拟数据初始化滚动视图可能会出现问题 正确,但是这种情况可以在代码中进行逻辑处理,因为初始对象可以是一些容易检测到的存根,可以有条件地显示诸如“加载”等内容。对我来说,这已经足够了……非常值得分享。【参考方案3】:

我发现的一个解决方法是在滚动视图中添加一个“不可见”Rectangle,并将width 设置为大于scrollView 中数据宽度的值

struct Object: Identifiable 
    var id: String


struct ContentView: View 
    @State var array = [Object]()

    var body: some View 
        GeometryReader  geometry in
            ScrollView(.vertical) 
                Rectangle()
                    .frame(width: geometry.size.width, height: 0.01)
                ForEach(array)  o in
                    Text(o.id)
                
            
        
        .onAppear(perform: 
            self.array = [Object(id: "1"),Object(id: "2"),Object(id: "3"),Object(id: "4"),Object(id: "5")]
        )
    

【讨论】:

【参考方案4】:

预期的行为发生在 Xcode 11.1 上,但不会出现在 Xcode 11.2.1

我在ScrollView 中添加了frame 修饰符,使ScrollView 出现

struct Object: Identifiable 
    var id: String


struct ContentView: View 
    @State var array = [Object]()

    var body: some View 
        ScrollView(.vertical) 
            ForEach(array)  o in
                Text(o.id)
            
        
        .frame(height: 40)
        .onAppear(perform: 
            self.array = [Object(id: "1"),Object(id: "2"),Object(id: "3"),Object(id: "4"),Object(id: "5")]
        )
    

【讨论】:

很遗憾无法在模拟器上的 iOS 13.2 上运行【参考方案5】:

借用 paulaysabellemedina,我想出了一个小助手视图,它可以按照我的预期处理事情。

struct ScrollingCollection<Element: Identifiable, Content: View>: View 
    let items: [Element]
    let axis: Axis.Set
    let content: (Element) -> Content

    var body: some View 
        Group 
            if !self.items.isEmpty 
                ScrollView(axis) 
                    if axis == .horizontal 
                        HStack 
                            ForEach(self.items)  item in
                                self.content(item)
                            
                        
                    
                    else 
                        VStack 
                            ForEach(self.items)  item in
                                self.content(item)
                            
                        
                    
                
            
            else 
                EmptyView()
            
        
    

【讨论】:

以上是关于SwiftUI ScrollView 没有更新?的主要内容,如果未能解决你的问题,请参考以下文章

带有 ScrollView 外观的 SwiftUI 错误

SwiftUI - ScrollView 没有一直滚动到底部

有没有办法在 SwiftUI 中制作分页的 ScrollView?

ScrollView 内容未填写 SwiftUI

SwiftUI - 如何获取 ScrollView 内容的大小(高度)

ScrollView 文本对齐 SwiftUI