I am presenting and dismissing a swiftUI view with a button, and it works fine.
The swiftUI view:
struct SmartG_SwiftUI: View {
var dismissAction: (() -> Void)
var body: some View {
Button(action: {
dismissAction()
}) {}
}
}
I am presenting the SwiftUI view controller from UIKit, this way:
let hostingVC = UIHostingVC(rootView: SmartG_SwiftUI(dismissAction: {
vc?.dismiss( animated: true, completion: nil )
}))
vc?.present(hostingVC, animated: true, completion: nil)
My question is, how could I put this button in a separate struct? So in order to have something like:
struct SmartG_SwiftUI: View {
var dismissAction: (() -> Void)
Header()
}
struct Header: View {
Button(action: {
dismissAction() //unknown here
}) {}
}
CodePudding user response:
Rather than hand-rolling your own dismiss action and passing it in, SwiftUI does have its own dismiss action available via an environment variable. I’ve not yet used it within a hosting controller basis, but conversely haven’t seen any indication that it doesn’t work... (edit: have double-checked and definitely works for a SwiftUI view wrapped in a UIHostingController
and presented via UIViewController.present(_:animation:completion:)
.)
The general approach is:
struct MyView: View {
@Environment(\.dismiss) var dismiss
var body: some View {
Button {
dismiss()
} label: {
Text("Close")
}
}
}
But this doesn’t have to be the topmost view within your hosting controller; because the dismiss action is in the environment, it’ll be available in your Header
view as well.
Note that for iOS 13 or 14, the syntax is a little more verbose:
struct MyView: View {
@Environment(\.presentationMode) var presentationMode
var body: some View {
Button {
presentationMode.wrappedValue.dismiss()
} label: {
Text("Close")
}
}
}