获取最顶级的UIViewController

我似乎无法获得最高UIViewController没有访问UINavigationController 。 这是我到目前为止:

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

但是,它似乎没有做任何事情。 keyWindowrootViewController似乎也是非零值,所以可选的链接不应该是一个问题。

提前致谢!

注意: 做这样的事情是一个坏主意。 它打破了MVC模式。

presentViewController显示一个视图控制器。 它不会返回一个视图控制器。 如果你没有使用UINavigationController ,你可能正在寻找的UINavigationController ,你需要从根开始,遍历所呈现的视图。

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

基于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的答案 ,所以这里是它的快速3版本。 这基本上是一样的,但是他错过了大括号,一些语法/variables/方法名称已经改变。 所以在这里!

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

使用这个代码find最顶级的UIViewController

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

基于上面的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; } } } } 

你可以在AppDelegate中定义一个UIViewControllervariables,并且在每个viewWillAppear中设置variables为self(但是dianz的回答是最好的答案)。

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

在Swift 3中find可见的viewController

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

此代码查找最后添加或最后一个活动控制器可见。

这个我在AppDelegate中用来查找活动视图控制器

你把代码放在哪里?

我在演示中尝试你的代码,我发现,如果你把代码放进去

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

将失败,因为关键窗口已经设置。

但是我把你的代码放在一些视图控制器中

 override func viewDidLoad() { 

它只是工作。