Dismiss a SwiftUI View that is contained in a UIHostingController

I found another approach that seems to work well and which feels a little cleaner than some of the other approaches. Steps:

  1. Add a dismissAction property to the SwiftUI view:
struct SettingsUIView: View {
    var dismissAction: (() -> Void)
    ...
}    
  1. Call the dismissAction when you want to dismiss the view:
Button(action: dismissAction ) {
    Text("Done")
}
  1. When you present the view, provide it with a dismissal handler:
let settingsView = SettingsUIView(dismissAction: {self.dismiss( animated: true, completion: nil )})
let settingsViewController = UIHostingController(rootView: settingsView )

present( settingsViewController, animated: true )

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

Tags:

Ios

Uikit

Swiftui