In the example code below:
OuterView
has a@State var number: Int? = 0
InnerView
expects a binding of typeInt
.OuterView
usesBinding.init(_: Binding<Value?>)
to convert fromBinding<Int?>
toBinding<Int>?
.- If
OuterView
setsnumber
tonil
, 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!