Member-only story
SwiftUI Binding Extensions
Making binding in SwiftUI views and previews as easy as ABC

Here are a few common SwiftUI issues that fall into the “there has to be a better way” category.
Optional Values
Let’s begin with optionals. It’s common to have optional values in our code due to API requirements, but working with them in SwiftUI can be a bit of a pain. Consider.
class SomeViewModel: ObservableObject {
@Published var name: String?
}
struct SomeView: View {
@StateObject var viewModel = SomeViewModel()
var body: some View{
TextField("Name", text: $viewModel.name) // does not compile
}
}
Here we have a view model with an optional name string and we want to be able to edit that value. Unfortunately, there’s no optional initializer for a TextField binding and the Swift compiler will give us an error. “Cannot convert value of type ‘Binding<String?>’ to expected argument type ‘Binding<String>’”.
What to do? I mean, if it was a Text
view we’d just use a nil coalescing operator to provide a default value for the string in question.
But how do we provide a default value for a binding?
Binding Extensions
You may have guessed part of the solution based on the article title. Yes, we’re going to create an extension to Binding.
Here’s the code.
extension Binding {
public func defaultValue<T>(_ value: T) -> Binding<T> where Value == Optional<T> {
Binding<T> {
wrappedValue ?? value
} set: {
wrappedValue = $0
}
}
}
And now, with that in place, we simply do.
struct SomeView: View {
@StateObject var viewModel = SomeViewModel()
var body: some View{
TextField("Name", text: $viewModel.name.defaultValue(""))
}
}
All we need to do is give our string a default value and we’re good to go. The extension will provide the value of name if it exists, or the default value if it does not. Either way, it looks like an non-optional binding to the text field, so our code now works as expected.