There are a lot of similar questions on SO that I have found and tried to implement. None of them work properly for a dynamic array in the way I'm using it, so I don't think this is a duplicate. I tried a lot of solutions from others. The best I can find is this one. But none of these work for dynamic arrays and ForEach
.
How do I loop over an @State
struct's array and bind to those values?
I have the following example code:
struct Items {
var items: [Item] = [Item(text: "test1"), Item(text: "test2"), Item(text: "test3")]
// Lots of functions to work with items in my program
}
struct Item: Identifiable {
let id = UUID()
var text: String
// Lots of other properties on an item
}
struct WindsView: View {
@State private var myItems = Items()
var body: some View {
NavigationView {
Form {
Section(header: Text("Test")) {
// This does not work of course, as item is not a Binding
ForEach(myItems.items) { item in
NumberTextField<Int>("Item Text", number: item, isDecimalAllowed: false)
}
}
Section(header: Text("Test2")) {
// This is what most solutions come up with. However, my `MyItems`
// can have elements removed. If you run the code and click the button
// below, you will see that it breaks with an index out of range.
ForEach(myItems.items.indices) { i in
TextField("Item Text", text: $myItems.items[i].text)
}
}
Button("Break Me") { myItems.items.popLast() }
}.navigationTitle("Help Me")
}
}
}
I understand why it doesn't work without passing in a binding, and why it crashes when I use indices. So I'm trying to figure out how to do this right.
Screenshots (With the code that clearly doesn't work commented out) before pushing the button:
And after pushing it