60

If I push view controllers and/or present modal view controllers on a UINavigationController, how can I find out what is the top most UIViewController? Or in my case, I want to know if a certain UITableViewController is the top most or not.

I tried using:

self.navigationController.topViewController == self

... but this doesn't work. I'm guessing that it's failing because I'm presenting modal view controllers on top of it and that the topViewController only keeps track of which views were pushed on the UINavigationController (as opposed to those that were presented modally).

KlimczakM
  • 12,576
  • 11
  • 64
  • 83
Senseful
  • 86,719
  • 67
  • 308
  • 465
  • Related: [How to tell if UIViewController's view is visible](http://stackoverflow.com/questions/2777438/how-to-tell-if-uiviewcontrollers-view-is-visible) – Senseful Jul 08 '13 at 18:10

3 Answers3

102

You want visibleViewController:

The currently visible view can belong either to the view controller at the top of the navigation stack or to a view controller that was presented modally.

Adam Ernst
  • 52,440
  • 18
  • 59
  • 71
  • Could you please check this out: I want to know how to use visibleViewController to compare with the view that I am looking for. http://stackoverflow.com/questions/7498880/how-to-determine-which-view-loads-on-returning-to-foreground-from-the-background – Namratha Sep 22 '11 at 04:25
  • 3
    Note that this is only for `UINavigationController`; if you don't have one of these, you'll need to use other means. – Ky - Oct 21 '15 at 21:43
23
NSArray *viewContrlls=[[self navigationController] viewControllers];

[viewContrlls lastObject];
Luke
  • 11,426
  • 43
  • 60
  • 69
Swastik
  • 2,415
  • 2
  • 31
  • 61
0

I know the question is old, but it's still popular - that's why I'd like to post my best solution which handles different UIViewController's subclasses. At the same time you can extend functionality of this method by your custom "collection" controllers such as side menu.

extension UIWindow {

  var visibleViewController: UIViewController? {
    guard let rootViewController = rootViewController else {
      return nil
    }
    return visibleViewController(for: rootViewController)
  }

  private func visibleViewController(for controller: UIViewController) -> UIViewController {
    var nextOnStackViewController: UIViewController? = nil
    if let presented = controller.presentedViewController {
      nextOnStackViewController = presented
    } else if let navigationController = controller as? UINavigationController,
      let visible = navigationController.visibleViewController {
      nextOnStackViewController = visible
    } else if let tabBarController = controller as? UITabBarController,
      let visible = (tabBarController.selectedViewController ??
        tabBarController.presentedViewController) {
      nextOnStackViewController = visible
    }

    if let nextOnStackViewController = nextOnStackViewController {
      return visibleViewController(for: nextOnStackViewController)
    } else {
      return controller
    }
  }

}
Timur Bernikovich
  • 5,660
  • 4
  • 45
  • 58