问题描述
我有以下组件可以呈现半透明字符网格:
I have the following component that renders a grid of semi transparent characters:
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()
}
}
}
settings
是一个 EnvironmentObject
settings
is an EnvironmentObject
每当 settings
更新时,最外面的 VStack
中的 Text 都会正确更新.但是,视图的其余部分不会更新(网格具有与以前相同的尺寸).这是为什么?
Whenever settings
is updated the Text in the outermost VStack
is correctly updated. However, the rest of the view is not updated (Grid has same dimenstions as before). Why is this?
第二个问题:为什么不能访问内部 ForEach
循环中的 i
并将其作为参数传递给函数?
Second question:Why is it not possible to access the i
in the inner ForEach
-loop and pass it as a argument to the function?
我在外部 ForEach
循环中遇到错误:
I get an error at the outer ForEach
-loop:
无法推断通用参数数据"
推荐答案
TL;DR
您的 ForEach 需要在您的范围后添加 id: \.self
.
ForEach 有几个初始值设定项.您正在使用
ForEach has several initializers. You are using
init(_ data: Range<Int>, @ViewBuilder content: @escaping (Int) -> Content)
其中 data
必须 是一个常量.
where data
must be a constant.
如果您的范围可能会发生变化(例如,您正在从数组中添加或删除项目,这将更改上限),那么您需要使用
If your range may change (e.g. you are adding or removing items from an array, which will change the upper bound), then you need to use
init(_ data: Data, id: KeyPath<Data.Element, ID>, content: @escaping (Data.Element) -> Content)
您为 id
参数提供了一个键路径,它唯一地标识了 ForEach
循环遍历的每个元素.在 Range
的情况下,您循环的元素是一个 Int
指定数组索引,它是唯一的.因此,您可以简单地使用 \.self
键路径让 ForEach 通过其自己的值识别每个索引元素.
You supply a keypath to the id
parameter, which uniquely identifies each element that ForEach
loops over. In the case of a Range<Int>
, the element you are looping over is an Int
specifying the array index, which is unique. Therefore you can simply use the \.self
keypath to have the ForEach identify each index element by its own value.
实际操作如下:
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
}
}
}
}
如果你运行它,你会看到当你按下按钮将项添加到数组时,它们将自动出现在 VStack
中.如果您删除id: \.self
",您将看到原始错误:
If you run that, you'll see that as you press the button to add items to the array, they will appear in the VStack
automatically. If you remove "id: \.self
", you'll see your original error:
`ForEach(_:content:)` should only be used for *constant* data.
Instead conform data to `Identifiable` or use `ForEach(_:id:content:)`
and provide an explicit `id`!"
这篇关于视图不会在嵌套 ForEach 循环中重新呈现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!