Obtenha o máximo de UIViewController

Eu não consigo obter o melhor UIViewController sem access a um UINavigationController . Aqui está o que eu tenho até agora:

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

No entanto, não parece fazer nada. O keyWindow e o rootViewController parecem ser valores não-nulos, então o encadeamento opcional não deve ser um problema.

Desde já, obrigado!

NOTA: É uma má ideia fazer algo assim. Isso quebra o padrão MVC.

presentViewController mostra um controlador de visualização. Não retorna um controlador de visualização. Se você não estiver usando um UINavigationController , provavelmente está procurando o UINavigationController e precisará iniciar na raiz e percorrer as exibições apresentadas.

 if var topController = UIApplication.sharedApplication().keyWindow?.rootViewController { while let presentedViewController = topController.presentedViewController { topController = presentedViewController } // topController should now be your topmost view controller } 

Para o Swift 3+:

 if var topController = UIApplication.shared.keyWindow?.rootViewController { while let presentedViewController = topController.presentedViewController { topController = presentedViewController } // topController should now be your topmost view controller } 

tem essa extensão

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

Você pode usar isso em qualquer lugar no seu controlador

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

Uso:

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

Para o swift4 encontrar o viewController superior

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

Como usar

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

Baseado na resposta de Dianz, a versão 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; } 

Eu amei a resposta do @dianz , e aqui está a versão do swift 3 dele. É basicamente a mesma coisa, mas a dele não continha uma chave e alguns dos nomes da syntax / variável / método foram alterados. Então aqui está!

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

O uso ainda é o mesmo:

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

Use este código para encontrar o melhor UIViewController

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

você pode definir uma variável UIViewController em AppDelegate e em cada viewWillAppear definir a variável como self (no entanto, dianz answer é a melhor resposta).

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

Baseado em Bob-c acima:

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

Onde você colocou o código?

Eu tentei o seu código na minha demonstração, eu descobri, se você colocar o código em

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

falhará, porque a janela principal já foi configurada.

Mas eu coloquei seu código em algum controlador de visão

 override func viewDidLoad() { 

Apenas funciona.

Para encontrar o viewController visível no Swift 3

 if let viewControllers = window?.rootViewController?.childViewControllers { let prefs = UserDefaults.standard if viewControllers[viewControllers.count - 1] is ABCController{ print("[ABCController] is visible") } } 

Este código encontra o último adicionado ou o último controlador ativo visível.

Isso eu usei no AppDelegate para encontrar a visão ativa Controller

https://gist.github.com/db0company/369bfa43cb84b145dfd8 Fiz alguns testes nas respostas e comentários neste site. Para mim, os seguintes trabalhos

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

Então, pegue o top viewController por:

 UIApplication.shared.topMostViewController()