Получить самый лучший UIViewController

Я не могу, кажется, получить самый верхний UIViewController текст UINavigationController. Вот что у меня есть до сих пор:

UIApplication.sharedApplication().keyWindow?.rootViewController?.presentViewController(vc, animated: true, completion: nil)

однако, похоже, он ничего не делает. The keyWindow и rootViewController похоже, что значения не равны нулю, поэтому необязательная цепочка не должна быть проблемой.

спасибо заранее!

Примечание: это плохая идея, чтобы сделать что-то подобное. Это нарушает шаблон MVC.

12 ответов


presentViewController показывает контроллер представления. Он не возвращает контроллер вида. Если вы не используете UINavigationController, вы, вероятно, искали presentedViewController и вам нужно будет начать с корня и перебирать представленные представления.

if var topController = UIApplication.sharedApplication().keyWindow?.rootViewController {
    while let presentedViewController = topController.presentedViewController {
        topController = presentedViewController
    }

    // topController should now be your topmost view controller
}

Для Swift 3+:

if var topController = UIApplication.shared.keyWindow?.rootViewController {
    while let presentedViewController = topController.presentedViewController {
        topController = presentedViewController
    }

    // topController should now be your topmost view controller
}

номера

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
    }
}

вы можете использовать это в любом месте на геймпаде

if let topController = UIApplication.topViewController() {

}

extension UIWindow {

func visibleViewController() -> UIViewController? {
    if let rootViewController: UIViewController = self.rootViewController {
        return UIWindow.getVisibleViewControllerFrom(rootViewController)
    }
    return nil
}

class func getVisibleViewControllerFrom(vc:UIViewController) -> UIViewController {
    if vc.isKindOfClass(UINavigationController.self) {
        let navigationController = vc as UINavigationController
        return UIWindow.getVisibleViewControllerFrom( navigationController.visibleViewController)
    } else if vc.isKindOfClass(UITabBarController.self) {
        let tabBarController = vc as UITabBarController
        return UIWindow.getVisibleViewControllerFrom(tabBarController.selectedViewController!)
    } else {
        if let presentedViewController = vc.presentedViewController {
            return UIWindow.getVisibleViewControllerFrom(presentedViewController!)
        } else {
            return vc
        }
    }
}

использование:

if let topController = window.visibleViewController() {
    println(topController)
}

для swift4, чтобы найти самый верхний viewController

extension UIApplication {
    class func getTopMostViewController(base: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {
        if let nav = base as? UINavigationController {
            return getTopMostViewController(base: nav.visibleViewController)
        }
        if let tab = base as? UITabBarController {
            if let selected = tab.selectedViewController {
                return getTopMostViewController(base: selected)
            }
        }
        if let presented = base?.presentedViewController {
            return getTopMostViewController(base: presented)
        }
        return base
    }
 }

как использовать

if let topVC = UIApplication.getTopMostViewController() {
   topVC.view.addSubview(forgotPwdView)
}

основываясь на ответе Dianz, версия Objective-C

- (UIViewController *) topViewController {
   UIViewController *baseVC = UIApplication.sharedApplication.keyWindow.rootViewController;
   if ([baseVC isKindOfClass:[UINavigationController class]]) {
       return ((UINavigationController *)baseVC).visibleViewController;
   }

   if ([baseVC isKindOfClass:[UITabBarController class]]) {
       UIViewController *selectedTVC = ((UITabBarController*)baseVC).selectedViewController;
       if (selectedTVC) {
           return selectedTVC;
       }
   }

   if (baseVC.presentedViewController) {
       return baseVC.presentedViewController;
   }
   return baseVC;
}

Я люблю @dianz это, и вот версия swift 3. Это в основном то же самое, но у него отсутствовала фигурная скобка, и некоторые имена синтаксиса/переменной/метода изменились. Вот оно!

extension UIApplication {
    class func topViewController(base: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {
        if let nav = base as? UINavigationController {
            return topViewController(base: nav.visibleViewController)
        }
        if let tab = base as? UITabBarController {
            if let selected = tab.selectedViewController {
                return topViewController(base: selected)
            }
        }
        if let presented = base?.presentedViewController {
            return topViewController(base: presented)
        }
        return base
    }
}

использование по-прежнему то же самое, хотя:

if let topController = UIApplication.topViewController() {
    print("The view controller you're looking at is: \(topController)")
}

используйте этот код, чтобы найти самый верхний UIViewController

func getTopViewController() -> UIViewController? {
    var topController: UIViewController? = UIApplication.shared.keyWindow?.rootViewController
    while topController?.presentedViewController != nil {
        topController = topController?.presentedViewController
    }
    return topController
}

вы можете определить переменную UIViewController в AppDelegate, и в каждом viewWillAppear установите переменную в self.(однако dianz ответ является лучшим ответом.)

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)
    let appDel = UIApplication.sharedApplication().delegate as! AppDelegate
    appDel.currentVC = self
}

на основе Bob-c выше:

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;
            }
        }
    }
}

куда вы положили код?

Я попробую ваш код в моем демо, я узнал, если вы поместите код в

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 

не получится, так как окна ключ настройки.

но я поместил ваш код в некоторый контроллер вида

override func viewDidLoad() {

Он просто работает.


чтобы найти видимый viewController в Swift 3

if let viewControllers = window?.rootViewController?.childViewControllers {

     let prefs = UserDefaults.standard

     if viewControllers[viewControllers.count - 1] is ABCController{
        print("[ABCController] is visible")

     }
}

этот код находит последний добавленный или последний активный контроллер.

Это я использовал в AppDelegate, чтобы найти активный контроллер вида


https://gist.github.com/db0company/369bfa43cb84b145dfd8 Я сделал несколько тестов на ответы и комментарии на этом сайте. Для меня, следующие работы

extension UIViewController {
    func topMostViewController() -> UIViewController {

        if let presented = self.presentedViewController {
            return presented.topMostViewController()
        }

        if let navigation = self as? UINavigationController {
            return navigation.visibleViewController?.topMostViewController() ?? navigation
        }

        if let tab = self as? UITabBarController {
            return tab.selectedViewController?.topMostViewController() ?? tab
    }

        return self
    }
}

extension UIApplication {
    func topMostViewController() -> UIViewController? {
        return self.keyWindow?.rootViewController?.topMostViewController()
    }
}

затем получите верхний viewController по:

UIApplication.shared.topMostViewController()