0

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:

enter image description here

And after pushing it

enter image description here

Diesel
  • 5,099
  • 7
  • 43
  • 81
  • Doesn't compile, can you show code for `Item.items`? – aheze May 16 '21 at 21:43
  • 1
    https://stackoverflow.com/questions/63079221/deleting-list-elements-from-swiftuis-list - similar issue – New Dev May 16 '21 at 22:03
  • @aheze the code is in the example as posted. The Items struct initialized it for the example code. It should run. – Diesel May 16 '21 at 23:34
  • `$myItems[i]` Will never run `$myItems[i]` is not an array `$myItems.items[i]` breaks because the item disappears before the View is reloaded. How to fix it there are many ways it all depends on your use case. 1 make `Item` an `ObservableObject` 2 use a custom `Binding(get:{},set:{})` – lorem ipsum May 17 '21 at 01:01
  • @NewDev that's the answer I was looking for. Thanks for finding it, I was focusing too much on foreach in my search. – Diesel May 17 '21 at 10:23

0 Answers0