I'm wondering how to best "promote" a Binding<Value?>
to a Binding<Value>
for cases where a model property is optional (e.g. a Core Data generated class) but the bound view does not accept optional values. Here's an example use case:
import SwiftUI
class Model: ObservableObject {
@Published var title: String?
}
struct EditModelView: View {
@ObservedObject var model: Model
var body: some View {
VStack {
Text(model.title ?? "nil")
TextField("Title", text: $model.title) // Doesn't compile: Cannot convert value of type 'Binding<String?>' to expected argument type 'Binding<String>'
}
}
}
I was thinking about something like this (limited to Strings):
extension Binding where Value == String? {
func onNone(_ fallback: String) -> Binding<String> {
return Binding<String>(get: {
return self.wrappedValue ?? fallback
}) { value in
self.wrappedValue = value
}
}
}
And usage would be:
TextField("Title", text: $model.title.onNone(""))
This seems to work the way I want (provides the default value when the original Binding's wrapped value is nil) but I'm wondering if there are potential gotchas with chaining Bindings in this way.
Questions:
- Does something like this already exist in SwiftUI?
- Is this a good or bad idea?
- Are there any concerns about how the original Binding's
Transaction
is not used? It's unclear to me how it would be applied. - Is there a way to write this in a more generalized way? e.g. something along the lines of:
extension Binding where Value == Optional<Wrapped> {
func onNone(_ fallback: Wrapped) -> Binding<Wrapped> {
return Binding<Wrapped>(get: {
return self.wrappedValue ?? fallback
}) { value in
self.wrappedValue = value
}
}
}