Reputation: 49590
Is there a standard way to bind, say, a TextField
to an associated value of an enum?
So, given this:
enum Choice {
case one(String)
case two(String)
}
Can I use it in some way as a binding in the View:
@State var choice: Choice = .one("")
var body: some View {
TextField("", text: $choice) // <- this clearly wouldn't work
}
Such that if choice
was set to choice = .one("")
, then TextField would update the associated value of one
.
EDIT
To clarify, can just the associated value of each be bound, so if the choice
variable is .one
, then .one
's associated value would change; same with .two
, and so forth.
Upvotes: 11
Views: 5918
Reputation: 257563
Here is a demo of possible solution. Tested with Xcode 11.4
struct TestBindToCase: View {
@State var choice: Choice = .one("")
var body: some View {
VStack {
ChoiceField
Divider()
Button("Assign") { self.choice = .one("Unknown") }
}
}
var ChoiceField: some View {
let boundCase = Binding(
get: {
if case let .one(value) = self.choice {
return value
} else { return "" }
},
set: { self.choice = .one($0) })
return TextField("", text: boundCase) // << works
}
}
Upvotes: 1
Reputation: 236305
You can extend your enumeration and add a text property with a getter and a setter:
extension Choice {
var text: String {
get {
switch self {
case let .one(string): return string
case let .two(string): return string
}
}
set {
switch self {
case .one: self = .one(newValue)
case .two: self = .two(newValue)
}
}
}
}
Then you can simply pass the text property:
TextField("", text: $choice.text)
Upvotes: 9