Hampden123
Hampden123

Reputation: 1258

Using SwiftUI ForEach's iterator variable in a binding call

I am trying to use ForEach's iterator variable in a view that requires binding.

import SwiftUI

struct MyStruct: Identifiable {
    public var id = UUID()
    var name: String
    var repetitions: Int

}

struct ContentView: View {
    @State private var mystructs :[MyStruct] = [
        MyStruct(name: "John", repetitions: 3),
        MyStruct(name: "Mark", repetitions: 9)
    ]

    var body: some View {

        List {
            ForEach (mystructs) { st in
                VStack {
                    Text("\(st.name)")
                    TextField("Name", text: self.$mystructs[0].name)
                    TextField("Name", text: $st.name) // <- Got "Ambiguous reference..." error
                }
            }
        }
    }
}

The ForEach iterator works, as demonstrated by the Text view's use of st.name. And the first TextField demonstrates that binding to mystructs' element works. However, for the second TextField which is my real use case, causes the following compiler errors:

- Use of unresolved identifier $st
- Ambiguous reference to member of 'subscript'

Any thoughts?

Upvotes: 0

Views: 196

Answers (3)

markiv
markiv

Reputation: 1664

Building on @Asperi's answer, this also works:

var body: some View {
    List {
        Button("Add") {
            self.mystructs.append(MyStruct(name: "Pepe", repetitions: 42))
        }
        ForEach(mystructs.indices, id: \.self) { index in
            VStack {
                Text(self.mystructs[index].name)
                TextField("Name", text: self.$mystructs[index].name)
            }
        }
    }
}

Upvotes: 1

Asperi
Asperi

Reputation: 257493

In the described scenario it can be done the following

ForEach (mystructs.indices) { i in
    VStack {
        Text("\(self.mystructs[i].name)")
        TextField("Name", text: self.$mystructs[i].name)
    }
}

Update: variant for more generic use-case

ForEach (Array(mystructs.enumerated()), id: \.element.id) { (i, item) in
    VStack {
        Text("\(item.name)")
        TextField("Name", text: self.$mystructs[i].name)
    }
}

Upvotes: 1

Anjali Aggarwal
Anjali Aggarwal

Reputation: 629

$st is coming as unresolved as 'st' is not a state variable and cannot be used for binding purpose.
Also $mystructs is working because it is a declared as a State variable and can be used for binding.

Hope this is of some use for you!Thanks!

Upvotes: 1

Related Questions