2
votes

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?

1
I came up with a potential solution: introduce a new @State Bool-flag to allow the view controller to indicate errors and propagate changes of this flag in a onDismiss closure to isShowingAlert. This way the alert will be presented only after the sheet is dismissed.mschmidt

1 Answers

1
votes

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.