SwiftUI Optional TextField

Ultimately the API doesn't allow this - but there is a very simple and versatile workaround:

extension Optional where Wrapped == String {
    var _bound: String? {
        get {
            return self
        }
        set {
            self = newValue
        }
    }
    public var bound: String {
        get {
            return _bound ?? ""
        }
        set {
            _bound = newValue.isEmpty ? nil : newValue
        }
    }
}

This allows you to keep the optional while making it compatible with Bindings:

TextField($test.bound)

You can add this operator overload, then it works as naturally as if it wasn't a Binding.

func ??<T>(lhs: Binding<Optional<T>>, rhs: T) -> Binding<T> {
    Binding(
        get: { lhs.wrappedValue ?? rhs },
        set: { lhs.wrappedValue = $0 }
    )
}

This creates a Binding that returns the left side of the operator's value if it's not nil, otherwise it returns the default value from the right side.

When setting it only sets lhs value, and ignores anything to do with the right hand side.

It can be used like this:

TextField("", text: $test ?? "default value")

Tags:

Swiftui