In the example code below:
OuterView has a @State var number: Int? = 0
InnerView expects a binding of type Int.
OuterView uses Binding.init(_: Binding<Value?>) to convert from Binding<Int?> to Binding<Int>?.
If OuterView sets number to nil, there is a runtime crash:
BindingOperations.ForceUnwrapping.get(base:) + 160
InnerView is being evaluated (executing body?) when number is nil despite the fact that it shouldn't exist in that configuration. Is this a bug or expected behavior?
struct OuterView: View {
@State var number: Int? = 1
var body: some View {
if let binding = Binding($number) {
InnerView(number: binding)
}
Button("Doesn't Crash") { number = 0 }
Button("Crashes") { number = nil }
}
}
struct InnerView: View {
@Binding var number: Int
var body: some View {
Text(number.formatted())
}
}
There is a workaround that involves adding an extension to Optional<Int>:
extension Optional<Int> {
var nonOptional: Int {
get { self ?? 0 }
set { self = newValue }
}
}
And using that to ensure that the binding has a some value even when number is nil.
if number != nil {
InnerView(number: $number.nonOptional)
}
This works, but I don't understand why it's necessary. Any insight would be greatly appreciated!