addChildされている時も最前面のViewControllerを取得したい

はじめに

最前面のVCを取得するコードをネット上で探すと【Swift】最前面のViewControllerの取得方法(備忘録)の記事が一番初めにヒットして以下のようなコードが記載されていますが、そのままだとaddchildでchildViewControllerとして追加されているVCを辿ることができず、rootにあるViewControllerが帰ってきてしまう問題にぶち当たりました。

func topViewController(controller: UIViewController?) -> UIViewController? {
    if let tabController = controller as? UITabBarController {
        if let selected = tabController.selectedViewController {
            return topViewController(controller: selected)
        }
    }

    if let navigationController = controller as? UINavigationController {
        return topViewController(controller: navigationController.visibleViewController)
    }

    if let presented = controller?.presentedViewController {
        return topViewController(controller: presented)
    }

    return controller
}

解決策

子VCがaddChildで追加されている場合を考慮して以下のように改造して使っています、基本的に親子関係を作る際は子VCは1つだと思うのでchildren.firstを渡しています。

class func topViewController(controller: UIViewController? = UIApplication.shared.windows.filter {$0.isKeyWindow}.first?.rootViewController) -> UIViewController? {

        if let navigationController = controller as? UINavigationController {
            return topViewController(controller: navigationController.visibleViewController)
        }

        if let tabController = controller as? UITabBarController {
            if let selected = tabController.selectedViewController {
                return topViewController(controller: selected)
            }
        }

        if let presented = controller?.presentedViewController {
            return topViewController(controller: presented)
        }

        // 子VCがいる時に子供を渡す
        if let childViewController: UIViewController = controller?.children.first {
            return topViewController(controller: childViewController)
        }

        return controller
    }