SwiftUIでdismissをするとき下記のキーを利用します。
https://developer.apple.com/documentation/swiftui/environmentvalues/dismiss
しかし対象OSバージョンに制限があります。
iOS14などでは下記を利用することになります。
https://developer.apple.com/documentation/swiftui/presentationmode/dismiss()
そして下記のExtensionによってOSでバージョン分けることができます。
extension EnvironmentValues {
// this can be used as: @Environment(\.dismissable) var myDismiss
// in any swiftui view and it will not complain about ios versions
var dismissable: () -> Void {
return dismissAction
}
// this function abstracts the availability check so you can
// avoid the conflicting return types and any other headache
private func dismissAction() {
if #available(iOS 15, *) {
dismiss()
} else {
presentationMode.wrappedValue.dismiss()
}
}
}
ただしpresentationMode.wrappedValue.dismiss()
ではUIHostingControllerの更に親のViewControllerを閉じることができません。こちらでは可能です。
OSバージョンで差異を出さずに閉じることのできるDismissKeyを作成します。
環境
OS: macOS 13.3.1
Xcode.app: Version 14.3 (14E222b)
動作iOSバージョン:13以上
CustomDismissAction
struct CustomDismissAction {
private var parentViewController: UIViewController
func callAsFunction(animated: Bool = true) {
parentViewController.dismiss(animated: animated)
}
init(_ parentViewController: UIViewController = UIViewController()) {
self.parentViewController = parentViewController
}
}
struct CustomDismissActionKey: EnvironmentKey {
static let defaultValue: CustomDismissAction = CustomDismissAction()
}
extension EnvironmentValues {
var customDismiss: CustomDismissAction {
get {
self[CustomDismissActionKey.self]
}
set {
self[CustomDismissActionKey.self] = newValue
}
}
}
extension View {
func setupDismissAction(_ parentViewController: UIViewController) -> some View {
environment(\.customDismiss, CustomDismissAction(parentViewController))
}
}
利用方法
HostingControllerを利用時にsetupDismissActionモディファイアで親のViewControllerを指定します。
class SwiftUIWrapViewController: UIViewController {
--略--
override func viewDidLoad() {
super.viewDidLoad()
--略--
let hostingController: UIHostingController = UIHostingController(
rootView: SwiftUIView()
.setupDismissAction(self)
)
--略--
}
}
DismissActionを利用する時のように@Environmentで定義し、利用したい箇所で呼びます。
@Environment(\.customDismiss) private var dismiss
今回作成したCustomDismissActionはこちらで公開していますのでご参考になればと思います。
https://github.com/kokiTakashiki/iOS14SupportDismissKey/tree/main
最後までお読みいただきありがとうございました。