iosuikitswiftui

Dismiss a SwiftUI View that is contained in a UIHostingController


I have rewritten my sign in view controller as a SwiftUI View. The SignInView is wrapped in a UIHostingController subclass (final class SignInViewController: UIHostingController<SignInView> {}), and is presented modally, full screen, when sign in is necessary.

Everything is working fine, except I can't figure out how to dismiss the SignInViewController from the SignInView. I have tried adding:

@Environment(\.isPresented) var isPresented

in SignInView and assigning it to false when sign in is successful, but this doesn't appear to interop with UIKit. How can I dismiss the view?


Solution

  • UPDATE: From the release notes of iOS 15 beta 1:

    isPresented, PresentationMode, and the new DismissAction action dismiss a hosting controller presented from UIKit. (52556186)


    I ended up finding a much simpler solution than what was offered:

    
    final class SettingsViewController: UIHostingController<SettingsView> {
        required init?(coder: NSCoder) {
            super.init(coder: coder, rootView: SettingsView())
            rootView.dismiss = dismiss
        }
    
        func dismiss() {
            dismiss(animated: true, completion: nil)
        }
    }
    
    struct SettingsView: View {
        var dismiss: (() -> Void)?
        
        var body: some View {
            NavigationView {
                Form {
                    Section {
                        Button("Dimiss", action: dismiss!)
                    }
                }
                .navigationBarTitle("Settings")
            }
        }
    }