0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

SwiftUIでCustomDismissActionを作成する

Posted at

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

CustomDismissActionKey
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

最後までお読みいただきありがとうございました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?