【问题标题】:How to refresh number of ForEach's displaying elements after array's size changes (SwiftUI, Xcode 11 Beta 5)如何在数组大小更改后刷新 ForEach 显示元素的数量(SwiftUI,Xcode 11 Beta 5)
【发布时间】:2019-08-02 17:16:29
【问题描述】:

我正在尝试实现一个视图,如果内容数组的大小发生变化,该视图可以更改显示项目的数量(由 ForEach 循环创建),就像购物应用程序在用户拉动刷新后如何更改其可用项目的数量一样

这是我目前尝试过的一些代码。如果我没记错的话,这些适用于 Xcode beta 4,但适用于 beta 5:

  • 如果数组的大小增加,循环仍会显示原始元素数
  • 数组大小减小会导致索引超出范围错误

代码:

import SwiftUI

struct test : View {
    @State var array:[String] = []
    @State var label = "not pressed"
    var body: some View {
        VStack{
            Text(label).onTapGesture {
                self.array.append("ForEach refreshed")
                self.label = "pressed"
            }
            ForEach(0..<array.count){number in
                Text(self.array[number])
            }
        }
}
}

#if DEBUG
struct test_Previews: PreviewProvider {
    static var previews: some View {
        test()
    }
}
#endif

总的来说,我是 SwiftUI 和 GUI 编程的新手,感觉就像每个内容都是在启动时定义的,之后很难进行更改(例如:在用户离开后重置视图然后返回) .非常感谢循环问题的解决方案或使视图更具动态性的任何提示!

【问题讨论】:

    标签: swift xcode swiftui xcode11


    【解决方案1】:

    Beta 5 发行说明说:

    Int 对 Identifiable 协议的追溯一致性是 删除。更改任何依赖此一致性的代码以通过 .self 到相关初始化程序的 id 参数。持续的 继续接受 Int 范围:

    List(0..<5) {
       Text("Rooms")
    }
    

    但是,您不应传递在运行时更改的范围。如果你 使用在运行时更改的变量来定义范围,列表 根据初始范围显示视图并忽略任何 范围的后续更新。

    您应该更改ForEach 以接收数组,而不是范围。理想情况下是Identifiable 数组,以避免使用\.self。但根据您的目标,这仍然可以工作:

    import SwiftUI
    
    struct ContentView : View {
        @State var array:[String] = []
        @State var label = "not pressed"
        var body: some View {
            VStack{
                Text(label).onTapGesture {
                    self.array.append("ForEach refreshed")
                    self.label = "pressed"
                }
                ForEach(array, id: \.self) { item in
                    Text(item)
                }
            }
        }
    }
    

    或者如 rob mayoff 建议的那样,如果您需要索引:

    struct ContentView : View {
        @State var array:[String] = []
        @State var label = "not pressed"
        var body: some View {
            VStack{
                Text(label).onTapGesture {
                    self.array.append("ForEach refreshed")
                    self.label = "pressed"
                }
                ForEach(array.indices, id: \.self) { index in
                    Text(self.array[index])
                }
            }
        }
    }```
    

    【讨论】:

    • 或者ForEach(array.indices, id: \.self)如果你需要数组索引。
    • 我总是忘记.indices。谢谢,我更新了答案。
    • Will ForEach(array.indices, id: \.self) 当数组改变时更新视图?
    • 如果 ForEach 中的视图需要绑定,所有这些解决方案都将不起作用。
    猜你喜欢
    • 2019-12-10
    • 1970-01-01
    • 2019-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-15
    • 2014-06-11
    • 2020-10-04
    相关资源
    最近更新 更多