视图不会在嵌套 ForEach 循环中重新呈现

sim*_*bac 20 swiftui

我有以下组件可以呈现半透明字符网格:

    var body: some View {
        VStack{
            Text("\(self.settings.numRows) x \(self.settings.numColumns)")
            ForEach(0..<self.settings.numRows){ i in
                Spacer()
                    HStack{
                        ForEach(0..<self.settings.numColumns){ j in
                            Spacer()
                            // why do I get an error when I try to multiply i * j
                            self.getSymbol(index:j)
                            Spacer()
                        }
                    }
                Spacer()
            }
        }
    }

Run Code Online (Sandbox Code Playgroud)

settings 是一个环境对象

每当settings更新时,最外层的文本VStack都会正确更新。但是,视图的其余部分不会更新(网格具有与以前相同的尺寸)。为什么是这样?

第二个问题:为什么不能访问i内部ForEach循环并将其作为参数传递给函数?

我在外ForEach循环出现错误:

无法推断通用参数“数据”

Joh*_* M. 59

TL; 博士

您的 ForEach 需要id: \.self在您的范围之后添加。

解释

ForEach 有几个初始化器。您正在使用

init(_ data: Range<Int>, @ViewBuilder content: @escaping (Int) -> Content)
Run Code Online (Sandbox Code Playgroud)

wheredata 必须是一个常数。

如果您的范围可能会发生变化(例如,您正在从数组中添加或删除项目,这将更改上限),那么您需要使用

init(_ data: Data, id: KeyPath<Data.Element, ID>, content: @escaping (Data.Element) -> Content)
Run Code Online (Sandbox Code Playgroud)

您为id参数提供一个键路径,它唯一地标识ForEach循环的每个元素。在 a 的情况下,Range<Int>您循环的元素是一个Int指定数组索引的元素,该索引是唯一的。因此,您可以简单地使用\.self键路径让 ForEach 通过其自己的值标识每个索引元素。

下面是它在实践中的样子:

struct ContentView: View {
    @State var array = [1, 2, 3]

    var body: some View {
        VStack {
            Button("Add") {
                self.array.append(self.array.last! + 1)
            }

            // this is the key part  v--------v
            ForEach(0..<array.count, id: \.self) { index in
                Text("\(index): \(self.array[index])")
                //Note: If you want more than one views here, you need a VStack or some container, or will throw errors
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

如果你运行它,你会看到当你按下按钮将项目添加到数组时,它们将VStack自动出现在。如果删除“ id: \.self”,您将看到原始错误:

`ForEach(_:content:)` should only be used for *constant* data. 
Instead conform data to `Identifiable` or use `ForEach(_:id:content:)`
and provide an explicit `id`!"
Run Code Online (Sandbox Code Playgroud)