I have the following component that renders a grid of semi transparent characters:
var body: some View {
Your ForEach needs id: \.self
added after your range.
ForEach has several initializers. You are using
init(_ data: Range, @ViewBuilder content: @escaping (Int) -> Content)
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, content: @escaping (Data.Element) -> Content)
You supply a keypath to the id
parameter, which uniquely identifies each element that ForEach
loops over. In the case of a Range
, 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.
Here is what it looks like in practice:
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..
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`!"