'Binding to an associated value of an enum

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.



Solution 1:[1]

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) 

Solution 2:[2]

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
    }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Leo Dabus
Solution 2 Charlton Provatas