SwiftUI ScrollView无法更新?


10

目标

获取要显示的数据 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上对此进行了测试,并获得了预期的结果(尽管滚动视图位于顶部而不是居中)。
sfung3

您也不需要关键字return
sfung3 '19

有趣的是,我使用的是Xcode 11.2,iOS 13.2,Swift 5
youjin,

是的,我之前有个print发言,因此return
youjin

我将更新到Xcode 11.2,看看是否可以重现此代码。可能需要一些时间,但我将向您介绍我的发现。
sfung3

Answers:


10

解决该问题的一种不太好用的方法是将ScrollView包含在IF语句中,该IF语句检查数组是否为空

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

此解决方法是完美的,谢谢!
亨德里克

1

预期的行为发生在Xcode 11.1但没有发生Xcode 11.2.1

我添加了一个frame修改器ScrollView,这使得在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上运行它
youjin

1

我发现如果状态初始化为某个值而不是空数组,它可以按预期工作(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,因此用虚拟数据初始化scrollView可能会遇到问题
youjin

是正确的,但是这种情况可以在代码中进行逻辑处理,因为初始对象可以是一些易于检测的存根,以便有条件地显示诸如“加载”等内容。对我来说,这足够了……非常值得分享。
阿斯佩里

1

我发现的一种变通办法是Rectangle在scrollView内添加一个“不可见的” ,其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")]
        })
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.