Reputation: 11547
How to convert Binding<String?> to Binding in SwiftUI
variable declared as:
@Binding var name: String?
Upvotes: 2
Views: 3352
Reputation: 1517
You can create your own Binding Extension
with default values for cases in where Value
is Optional
.
extension Binding where Value: Equatable {
/// Given a binding to an optional value, creates a non-optional binding that projects
/// the unwrapped value. If the given optional binding contains `nil`, then the supplied
/// value is assigned to it before the projected binding is generated.
///
/// This allows for one-line use of optional bindings, which is very useful for CoreData types
/// which are non-optional in the model schema but which are still declared nullable and may
/// be nil at runtime before an initial value has been set.
///
/// class Thing: NSManagedObject {
/// @NSManaged var name: String?
/// }
/// struct MyView: View {
/// @State var thing = Thing(name: "Bob")
/// var body: some View {
/// TextField("Name", text: .bind($thing.name, ""))
/// }
/// }
///
/// - note: From experimentation, it seems that a binding created from an `@State` variable
/// is not immediately 'writable'. There is seemingly some work done by SwiftUI following the render pass
/// to make newly-created or assigned bindings modifiable, so simply assigning to
/// `source.wrappedValue` inside `init` is not likely to have any effect. The implementation
/// has been designed to work around this (we don't assume that we can unsafely-unwrap even after
/// assigning a non-`nil` value), but a side-effect is that if the binding is never written to outside of
/// the getter, then there is no guarantee that the underlying value will become non-`nil`.
@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
static func bindOptional(_ source: Binding<Value?>, _ defaultValue: Value) -> Binding<Value> {
self.init(get: {
source.wrappedValue ?? defaultValue
}, set: {
source.wrappedValue = ($0 as? String) == "" ? nil : $0
})
}
}
struct ContentView: View {
@Binding var title: String?
var body: some View {
TextField("Title Value", text: .bindOptional($title, "Default Title"))
}
}
Upvotes: 1
Reputation: 257493
It depends where do you use it, but most probably, you'd need something, like
Binding(name) ?? .constant("")
In some cases it might be needed proxy binding created in place, like in https://stackoverflow.com/a/59274498/12299030.
For scenarios with arguments you can use approach like in https://stackoverflow.com/a/62217832/12299030.
Upvotes: 2