TL;DR: my app has some global alerts and modals (e.g. hints about trial limits, the in-app purchase screens, etc.) which should be available through out the app. In UIKit I could always present alerts or modals on the topmost view controller, no matter what was currently presented. In SwiftUI, .alert and .sheet are tied to the local view hierarchy, so triggering an alert from inside a sheet dismisses the sheet first.
Is there a SwiftUI-native pattern for presenting global alerts/sheets/modals on top of everything—without UIKit bridging and without rebuilding custom alert UIs?
I’m looking for a way in SwiftUI to show app-wide alerts or sheets, regardless of where the user currently is in the view hierarchy.
In UIKit this was simple: I just walked up the presentedViewController chain and called present(...) on the topmost view controller.
In SwiftUI, this approach doesn’t translate because .alert and .sheet, etc. belong to the currently visible view hierarchy.
class AppController: ObservableObject {
@Published var isShowingAlert = false
@Published var isShowingSheet = false
@Published var isShowingMsg = false
func showAlert() { isShowingAlert = true }
func showSheet() { isShowingSheet = true }
func showMsg() { isShowingMsg = true }
}
struct RootView: View {
@StateObject var appController = AppController()
var body: some View {
VStack {
Button("Show Alert") { appController.showAlert() }
Button("Show Sheet") { appController.showSheet() }
Button("Show Msg") { appController.showMsg() }
}
.alert("Title", isPresented: $appController.isShowingAlert) { }
.sheet(isPresented: $appController.isShowingSheet) {
SubViewA(appController: appController)
}
// additional modal
.sheet(isPresented: $appController.isShowingMsg) {
Text("Message")
}
}
}
struct SubViewA: View {
@ObservedObject var appController: AppController
var body: some View {
VStack {
Text("SubViewA")
// Will dissmiss SubViewA-Sheet and show alert on RootView
Button("Show Alert") { appController.showAlert() }
// Fails
Button("Show Msg") { appController.showMsg() }
}
}
}
If the alert is triggered inside the presented sheet (SubViewA), SwiftUI first dismisses the .sheet and only then shows the alert. So I cannot display a “global” alert on top of an existing .sheet. Showing another .sheet (or .fullscreenCover) over the existing sheet also fails.
I’m looking for a pure SwiftUI solution that:
- has no fallback to UIKit
- allows global alert/sheet presentation
- shows them above currently presented sheets
- does not rely on UIKit (UIViewController, present(...))
- does not require fully custom alert implementations
Is there a recommended, SwiftUI-native pattern for global, hierarchy-independent modal presentation? Or is this simply not possible with SwiftUI’s current presentation system?