It used like this:
ForEach($model.users) { $user in
VStack {
HStack {
// user is: var user { get set }
// where is it (no $ in front) from?
Text(user.name)
Spacer()
Toggle("User has been contacted", isOn: $user.isContacted)
.labelsHidden()
}
Text("Contacted: \(user.isContacted ? "Yes" : "No")")
}
}
The content closure parameter is declared as $user with this $ prefix. And user (without $) can be used to access the element value. Where is this user come to from?
The content closure parameter type is a Binding<[User]>.Element. Just by the look of the code, I thought $user is just conventional naming with this $ prefix to signify this is a binding. But the plain user variable is used to access the element as a value, seems some kind of code synthesis happen behind the scenes some how?
What's going on? I can use shorthand parameter $0 or omit the $ in the closure parameter name, but then there is no way to refer to the element as value.
My Test
import SwiftUI
struct User: Identifiable {
let id = UUID()
var name: String
var isContacted = false
}
final class Model: ObservableObject {
@Published var users: [User]
init(_ users: [User]) {
self.users = users
}
}
struct ContentView: View {
@EnvironmentObject private var model: Model
var body: some View {
List {
ForEach($model.users) { $user in
VStack {
HStack {
// user is: var user { get set }
// where is it (no $ in front) from?
Text(user.name)
Spacer()
Toggle("User has been contacted", isOn: $user.isContacted)
.labelsHidden()
}
Text("Contacted: \(user.isContacted ? "Yes" : "No")")
}
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
let data = [
User(name: "Larry"),
User(name: "Curly"),
User(name: "Moe")
]
ContentView()
.environmentObject(Model(data))
}
}