如果没有UINavigationController,我似乎无法得到最顶端的UIViewController。以下是我目前所掌握的:

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

然而,它似乎没有做任何事情。keyWindow和rootViewController似乎也不是nil值,所以可选的链接应该不是问题。

注意:这样做不是一个好主意。它打破了MVC模式。


当前回答

有这个扩展

斯威夫特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
    }
}

斯威夫特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() {
    
}

其他回答

@AlberZou略有变化,使用计算变量而不是函数

extension UIViewController {
  var 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 {
  var topMostViewController : UIViewController? {
    return self.keyWindow?.rootViewController?.topMostViewController
  }
}

然后说

if let topViewControler = UIApplication.shared.topMostViewController {
    ... do stuff
}
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
    }

在Swift 3中找到可见的viewController

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

     let prefs = UserDefaults.standard

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

     }
}

这段代码找到最后添加的或最后可见的活动控制器。

我已经在AppDelegate中使用它来查找活动视图控制器

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

在一个非常罕见的情况下,使用自定义segue,最顶层的视图控制器不在导航堆栈或选项卡栏控制器中或被呈现,但它的视图被插入到关键窗口子视图的顶部。

在这种情况下,有必要检查UIApplication.shared.keyWindow.subviews.last == self。视图来确定当前视图控制器是否是最顶端的。