Skip to main content
deleted 86 characters in body
Source Link
jonrsharpe
  • 123.3k
  • 31
  • 277
  • 488

TL;DR My: my app has some global alerts and modals (e.g. hints about trial limits, the in-app purchase screentscreens, etc.) which should be availabelavailable through out the app. In UIKitUIKit I could always present alerts or modals on the topmost view controller, no matter what was currently presented. In SwiftUISwiftUI, .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 SwiftUISwiftUI-native pattern for presenting global alerts/sheets/modals on top of everything—without UIKitUIKit bridging and without rebuilding custom alert UIs?

Question

I’m looking for a way in SwiftUISwiftUI to show app-wide alerts or sheets, regardless of where the user currently is in the view hierarchy.

In UIKitUIKit this was simple: I just walked up the presentedViewController chain and called present(...) on the topmost view controller.

In SwiftUISwiftUI, this approach doesn’t translate because .alert and .sheet, etc. belong to the currently visible view hierarchy.

The issue: If the alert is triggered inside the presented sheet (SubViewA), SwiftUISwiftUI 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.

What I’m looking for

A pure SwiftUI I’m looking for a pure SwiftUI solution that:

  • no has no fallback to UIKitUIKit
  • 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

In other words:

Is there a recommended, SwiftUI-nativeSwiftUI-native pattern for global, hierarchy-independent modal presentation? Or is this simply not possible with SwiftUI’s current presentation system?

TL;DR My app has some global alerts and modals (e.g. hints about trial limits, the in-app purchase screent, etc.) which should be availabel 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?

Question

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.

The issue: 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.

What I’m looking for

A pure SwiftUI solution that:

  • 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

In other words:

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?

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.

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?

Source Link
Andrei Herford
  • 19k
  • 24
  • 111
  • 267

How to present app-wide alerts/sheets above existing sheets in SwiftUI (central presenter like UIKit)?

TL;DR My app has some global alerts and modals (e.g. hints about trial limits, the in-app purchase screent, etc.) which should be availabel 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?


Question

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() }
        }
    }
}

The issue: 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.

What I’m looking for

A pure SwiftUI solution that:

  • 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

In other words:

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?