Reputation: 1112
Given my assumptions, from the code below, that:
$a
returns a Binding<Bool>
Binding.constant(a: self.a)
also returns a Binding<Bool>
then why does B(a: Binding<Bool?>)
reject (correctly) the first with "Cannot convert value of type 'Binding<Bool>' to expected argument type 'Binding<Bool?>'"
but accept the second?
import SwiftUI
struct ContentView: View {
@State var a: Bool = false
var body: some View {
A(a: $a)
}
}
struct A : View {
@Binding var a: Bool
var body: some View {
//B(a: $a)
// ^~~~
// Fails with "Cannot convert value of type 'Binding<Bool>' to expected argument type 'Binding<Bool?>'"
B(a: Binding.constant(self.a))
}
}
struct B : View {
@Binding var a: Bool?
var body: some View {
if a == nil {
return Text("a is nil")
} else {
return Text("a is \(a! ? "true" : "false")")
}
}
}
Upvotes: 1
Views: 3298
Reputation: 10355
What would you expect to happen to the contents of the non-optional Bool
held by A.a
if someone sets the derived optional Bool binding in B.b
to nil
? Your workaround of wrapping the Bool
in a .constant
works because it prevents that possibility (since a constant binding cannot be changed).
You could alternatively create a derived binding that simply ignores setting nil
values, like so (note the under-documented "_" prefix for assigning an underlying property wrapper value):
extension B {
init(reqA: Binding<Bool>) {
self._a = Binding<Bool?>(get: { reqA.wrappedValue },
set: { if let newValue = $0 { reqA.wrappedValue = newValue } })
}
}
Upvotes: 1