mschmidt
mschmidt

Reputation: 2790

Showing an Alert after presenting a Sheet

I have a SwiftUI-View MyView, that is presenting a view controller when a button is clicked. The presented view controller (implemented in UIKit and wrapped via UIViewControllerRepresentable in MyPresentedView ) gets a binding to isShowingAlert to indicate an error situation which should be handled by showing an alert after the sheet is dismissed.

struct MyView: View {
    @State private var isShowingSheet = false
    @State private var isShowingAlert = false

    var body: some View {
        Button(action: { self.isShowingSheet.toggle() }) {
            Text("Show Sheet")
        }
        .sheet(isPresented: $isShowingSheet) {
            MyPresentedView(alert: self.$isShowingAlert)
        }
        .alert(isPresented: $isShowingAlert) {
            Alert(title: Text("title"), message: Text("message"), dismissButton: .default(Text("OK")))
        }
    }
}

The problem: since the presented view controller toggles isShowingAlert while it is still presented, SwiftUI seems to try to present the alert while the sheet is still presented. This results in log messages like:

Warning: Attempt to present <SwiftUI.PlatformAlertController ...> on ... which is already presenting (null)

Is there a proper way to delay the .alert until after .sheet is dismissed?

Upvotes: 2

Views: 2376

Answers (2)

Swifty McSwifterton
Swifty McSwifterton

Reputation: 2667

I was able to do this by attaching the alert to the sheet view itself:

.sheet(isPresented: $showSheet, content: {
    YourSheetView()
    .presentationDragIndicator(.visible)
    .alert("", isPresented: self.$showDialog) {
        Button("Hello") {
            // button action stuff
        }
        Button("Cancel") {}
    } message: {
        Text("World")
    }
})

Upvotes: 1

mschmidt
mschmidt

Reputation: 2790

Just for the record, here is a sketch of the potential solution I mentioned in my comment:

struct MyView: View {
    @State private var isShowingSheet   = false
    @State private var errorDuringSheet = false
    @State private var isShowingAlert   = false

    var body: some View {
        Button(action: { self.isShowingSheet.toggle() }) {
            Text("Show Sheet")
        }
        .sheet(isPresented: $isShowingSheet, onDismiss: propagateError) {
            MyPresentedView(alert: self.$errorDuringSheet)
        }
        .alert(isPresented: $isShowingAlert) {
            Alert(title: Text("title"), message: Text("message"), dismissButton: .default(Text("OK")))
        }
    }

    func propagateError() {
        isShowingAlert   = errorDuringSheet
        errorDuringSheet = false
    }
}

Any better solution is still welcome.

Upvotes: 1

Related Questions