Get top most UIViewController

后端 未结 24 1876
别那么骄傲
别那么骄傲 2020-11-22 14:47

I can\'t seem to get the top most UIViewController without access to a UINavigationController. Here is what I have so far:

UIApplic         


        
相关标签:
24条回答
  • 2020-11-22 15:34

    have this extension

    Swift 2.*

    extension UIApplication {
        class func topViewController(controller: UIViewController? = UIApplication.sharedApplication().keyWindow?.rootViewController) -> UIViewController? {
            if let navigationController = controller as? UINavigationController {
                return topViewController(navigationController.visibleViewController)
            }
            if let tabController = controller as? UITabBarController {
                if let selected = tabController.selectedViewController {
                    return topViewController(selected)
                }
            }
            if let presented = controller?.presentedViewController {
                return topViewController(presented)
            }
            return controller
        }
    }
    

    Swift 3

    extension UIApplication {
        class func topViewController(controller: UIViewController? = UIApplication.shared.keyWindow?.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)
            }
            return controller
        }
    }
    

    You can you use this anywhere on your controller

    if let topController = UIApplication.topViewController() {
    
    }
    
    0 讨论(0)
  • 2020-11-22 15:35

    you can define a UIViewController variable in AppDelegate, and in every viewWillAppear set the variable to self.(however dianz answer is the best answer.)

    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)
        let appDel = UIApplication.sharedApplication().delegate as! AppDelegate
        appDel.currentVC = self
    }
    
    0 讨论(0)
  • 2020-11-22 15:36

    Based on Bob -c above:

    Swift 3.0

    extension UIWindow {
    
    
        func visibleViewController() -> UIViewController? {
            if let rootViewController: UIViewController  = self.rootViewController {
                return UIWindow.getVisibleViewControllerFrom(vc: rootViewController)
            }
            return nil
        }
    
        class func getVisibleViewControllerFrom(vc:UIViewController) -> UIViewController {
    
            if vc.isKind(of: UINavigationController.self) {
    
                let navigationController = vc as! UINavigationController
                return UIWindow.getVisibleViewControllerFrom( vc: navigationController.visibleViewController!)
    
            } else if vc.isKind(of: UITabBarController.self) {
    
                let tabBarController = vc as! UITabBarController
                return UIWindow.getVisibleViewControllerFrom(vc: tabBarController.selectedViewController!)
    
            } else {
    
                if let presentedViewController = vc.presentedViewController {
    
                    return UIWindow.getVisibleViewControllerFrom(vc: presentedViewController)
    
                } else {
    
                    return vc;
                }
            }
        }
    }
    
    0 讨论(0)
  • 2020-11-22 15:37
    import UIKit
    
    extension UIApplication {
    
        // MARK: Choose keyWindow as per your choice
        var currentWindow: UIWindow? {
            connectedScenes
            .filter({$0.activationState == .foregroundActive})
            .map({$0 as? UIWindowScene})
            .compactMap({$0})
            .first?.windows
            .filter({$0.isKeyWindow}).first
        }
    
        // MARK: Choose keyWindow as per your choice
        var keyWindow: UIWindow? {
            UIApplication.shared.windows.first { $0.isKeyWindow }
        }
    
        class func topMostViewController(base: UIViewController? = UIApplication.shared.currentWindow?.rootViewController) -> UIViewController? {
    
            if let nav = base as? UINavigationController {
                return topMostViewController(base: nav.visibleViewController)
            }
    
            if let tab = base as? UITabBarController {
                let moreNavigationController = tab.moreNavigationController
    
                if let top = moreNavigationController.topViewController, top.view.window != nil {
                    return topMostViewController(base: top)
                } else if let selected = tab.selectedViewController {
                    return topMostViewController(base: selected)
                }
            }
            if let presented = base?.presentedViewController {
                return topMostViewController(base: presented)
            }
            return base
        }
    }
    
    0 讨论(0)
  • 2020-11-22 15:38

    Use this code to find top most UIViewController

    func getTopViewController() -> UIViewController? {
        var topController: UIViewController? = UIApplication.shared.keyWindow?.rootViewController
        while topController?.presentedViewController != nil {
            topController = topController?.presentedViewController
        }
        return topController
    }
    
    0 讨论(0)
  • 2020-11-22 15:38

    For Swift 5+, iOS 13+

    extension UIViewController {
        static func topMostViewController() -> UIViewController? {
            if #available(iOS 13.0, *) {
                let keyWindow = UIApplication.shared.windows.filter {$0.isKeyWindow}.first
                return keyWindow?.rootViewController?.topMostViewController()
            }
            
            return UIApplication.shared.keyWindow?.rootViewController?.topMostViewController()
        }
        
        func topMostViewController() -> UIViewController? {
            if let navigationController = self as? UINavigationController {
                return navigationController.topViewController?.topMostViewController()
            }
            else if let tabBarController = self as? UITabBarController {
                if let selectedViewController = tabBarController.selectedViewController {
                    return selectedViewController.topMostViewController()
                }
                return tabBarController.topMostViewController()
            }
                
            else if let presentedViewController = self.presentedViewController {
                return presentedViewController.topMostViewController()
            }
            
            else {
                return self
            }
        }
    }
    

    Usage:

    When you are getting topMostViewController without instance of UIViewController

    guard let viewController = UIViewController.topMostViewController() else { return }
    print(viewController)
    

    When you are getting topMostViewController of instance of UIViewController

    let yourVC = UIViewController()
    guard let vc = yourVC.topMostViewController() else { return }
    print(vc)
    
    0 讨论(0)
提交回复
热议问题