Don’t Unwrap Optional Bindings
October 22, 2025
SwiftUI’s Binding has an initializer that turns a Binding<Value?> into a Binding?<Value>. This means that if you have an optional @State property, like this:
@State var user: User?
You can initialize a Binding to it like this:
if let user = Binding($user) {
}
That makes it possible to do this:
if let user = Binding($user) {
ProfileView(user: user)
}
Possible, but unsafe. If user becomes nil, your app will crash.
Here is a simple example:
struct OuterView: View {
@State var number: Int? = 1
var body: some View {
if let binding = Binding($number) {
InnerView(number: binding)
}
Button("Crash") { number = nil }
}
}
struct InnerView: View {
@Binding var number: Int
var body: some View {
Text(number.formatted())
}
}
The crash occurs here:
BindingOperations.ForceUnwrapping.get(base:) + 160
Somehow, InnerView gets evaluated when number is nil - even though InnerView can’t exist in that state.
The Alternative
My preferred workaround involves adding an extension to Optional:
extension Optional {
subscript(default default: Wrapped) -> Wrapped {
get {
self ?? `default`
}
set {
self = newValue
}
}
}
This subscript effectively turns an Optional<Wrapped> into a Wrapped. If the wrapped value is nil, it returns the provided default.
Use it like this:
if number != nil {
InnerView(number: $number[default: 0])
}
You will never see this default, but it will be required as the view hierarchy is re-evaluated. I’ve posted this finding on the Apple Developer Forums. If you have any insight as to why this is happening, please let me know!