9
4

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 3 years have passed since last update.

SwiftUI 環境で表示中のUIViewControllerを取得する

Posted at

概要

SwiftUIのプロジェクトで、現在フロントにあるUIViewControllerを手軽に取得する方法についてのTips

SwiftUIとUIKitの連携

SwiftUIのViewとUIKit間での連携は

  • UIHostingController
  • UIViewRepresentable

を使った方法がある。

ただ、SwiftUIのプロジェクトで外部ライブラリなど使用する場合に

いま提示している「UIViewController」を渡すことが必要になるケースがある。

例えば、Googleの「UserMessagingPlatform」を使って

ATT事前許諾プロンプトを提示する際に

SwiftUIのコンテキスト上からライブラリ側にUIViewControllerを渡す必要がある。

方法は他にも色々ありそうだが、その時の対応メモ。

現在のUIViewControllerを探す

表示中のUIViewControllerを探す流れは

まず

  1. UIApplicationから接続中のUISceneたちを取得
  2. 前面にあるアクティブなSceneをフィルタ
  3. SceneからUIWindowSceneを探す
  4. UIWindowSceneが持つUIWindowからKeyWindowを探す
  5. Windowから rootViewController or そこから生えているpresentedViewControllerを見つける

なお、ここで実際に取得できるのは

UIHostingController<SomeOneView>

となり

これを任意のライブラリなりに渡せば良い。

検証

// 1
let scenes = UIApplication.shared.connectedScenes
debugPrint(scenes)

// 2
let active_scenes = scenes.filter({$0.activationState == .foregroundActive})
debugPrint(active_scenes)

// 3
let window_scenes = active_scenes.map({$0 as? UIWindowScene})
debugPrint(window_scenes)

// 4
let windows = window_scenes.compactMap({$0}).first?.windows
debugPrint(windows)
let first_keywindow = windows?.filter({$0.isKeyWindow}).first
debugPrint(first_keywindow)

// 5
let vc = first_keywindow?.rootViewController
if let _vc = vc?.presentedViewController {
    debugPrint(String(describing: type(of: vc!)))
}else{
    debugPrint(String(describing: type(of: _vc)))
}

// UIHostingController<ContextView>

上をまとめたもの

例えば、UIViewControllerにExtensionで追加して


extension UIViewController {
    static func getFrontViewController() -> UIViewController? {
        let keyWindow = UIApplication.shared.connectedScenes
            .filter({$0.activationState == .foregroundActive})
            .map({$0 as? UIWindowScene})
            .compactMap({$0})
            .first?.windows
            .filter({$0.isKeyWindow}).first

        let vc = keyWindow?.rootViewController
        guard let _vc = vc?.presentedViewController else {
            return vc
        }
        return _vc
    }
}
guard let vc = UIViewController.getFrontViewController() else {
    return
}

// vc

みたいに使用したり。

9
4
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
9
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?