Search code examples
iosswiftuiuihostingcontroller

UIHostingView failed to present view, which already presenting


I create the custom alert, but when I try to show it on .sheet View, I have this error -

2023-08-05 00:21:15.880778+0200 MyApp[759:72430] [Presentation] Attempt to present <_TtGC7SwiftUI19UIHostingControllerV6Events11CustomAlert_: 0x108009600> on <_TtGC7SwiftUI19UIHostingControllerGVS_15ModifiedContentVS_7AnyViewVS_12RootModifier__: 0x103022800> (from <_TtGC7SwiftUI19UIHostingControllerGVS_15ModifiedContentVS_7AnyViewVS_12RootModifier__: 0x103022800>) which is already presenting <_TtGC7SwiftUI29PresentationHostingControllerVS_7AnyView_: 0x10680a000>.

this is my code -


extension View {
    func customAlert(args) -> some View {
        if let topController = UIApplication.shared.windows.first?.rootViewController {
           let alert = CustomAlert(args)
           let hostingController = UIHostingController(rootView: alert)
           hostingController.modalPresentationStyle = .overFullScreen
           hostingController.modalTransitionStyle = .crossDissolve
           hostingController.view.backgroundColor = .clear

           topController.present(hostingController, animated: false)
        }

        return self
     }
}

how can I fix it?

please help me! I don't now, why is it happing:(


Solution

  • .sheet modifier presents a view controller modally on the current window's root view controller. When we need to present a view controller on top of already presented view controller we can use presentedViewController property of UIViewController to check if the root view controller has already presented any VC.

    extension View {
        func customAlert(args) -> some View {
            if let topController = UIApplication.shared.windows.first?.rootViewController {
                let alert = CustomAlert(args)
                let hostingController = UIHostingController(rootView: alert)
                hostingController.modalPresentationStyle = .overFullScreen
                hostingController.modalTransitionStyle = .crossDissolve
                hostingController.view.backgroundColor = .clear
                
                // check if a VC is already presented modally
                if let presentedVC = topController.presentedViewController {
                    presentedVC.present(hostingController, animated: false)
                } else {
                    topController.present(hostingController, animated: false)
                }
            }
            
            return self
        }
    }