Defer alert-binding dismissal writes out of the view update (#1537)

SwiftUI invokes an alert Binding's setter inside the current view
update when the alert dismisses because its get re-evaluated (a
scenePhase change while the Bluetooth-off or voice-error alert is up).
Both root alert bindings wrote their @Published backing state
synchronously from that setter — the 'Publishing changes from within
view updates is not allowed' undefined-behavior warning, reproduced on
device by launching with Bluetooth off and backgrounding. Defer the
write one main-actor hop.

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
jack 2026-07-29 16:09:09 +01:00 committed by GitHub
parent c6b7096b2f
commit d39467f7d3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -182,7 +182,13 @@ struct ContentView: View {
!hasRootModalPresentation else {
return
}
appChromeModel.showBluetoothAlert = false
// SwiftUI can invoke this setter inside a view update (the
// alert dismisses when a scenePhase change re-evaluates the
// `get`); publishing synchronously there is undefined
// behavior, so defer the write one hop.
Task { @MainActor in
appChromeModel.showBluetoothAlert = false
}
}
)
}
@ -205,7 +211,11 @@ struct ContentView: View {
!hasRootModalPresentationBesidesVoiceAlert else {
return
}
voiceRecordingVM.showAlert = false
// Same deferral as the Bluetooth alert above: the setter can
// run inside a view update when the sheet state changes.
Task { @MainActor in
voiceRecordingVM.showAlert = false
}
}
)
}