1

I'm trying to access the frontmost controller of the Application during the user navigation using this code:

override func viewDidAppear(animated: Bool) {

    super.viewDidAppear(animated)
    println(UIApplication.sharedApplication().keyWindow?.rootViewController)

}

But it seems that the rootViewController always refers to the first controller defined by the storyboard independently by when I'm accessing that property.

Is there something I'm doing wrong or I've misunderstood about the rootViewController property?

MatterGoal
  • 16,038
  • 19
  • 109
  • 186

2 Answers2

1

rootViewController is indeed the topmost, ultimate view controller owned by UIWindow.

To get the currently displaying view controller, you need to walk down the controller hierarchy. Here is an Objective-C category that you can add to your application, and using a bridging header you'll easily be able to call this UIWindow category from your swift code.

Community
  • 1
  • 1
Michael Dautermann
  • 88,797
  • 17
  • 166
  • 215
0

OK, based on the code that Michael pointed out, I wrote some Swift (1.2) code to do the same thing. You can add this as an extension to UIViewController (as I did), UIApplication, or for that matter simply make it a global function.

extension UIViewController {

    static func getVisibleViewController () -> UIViewController {
        let rootViewController = UIApplication.sharedApplication().keyWindow?.rootViewController

        return getVisibleViewControllerFrom(rootViewController!)
    }

    static func getVisibleViewControllerFrom(viewController: UIViewController) -> UIViewController {
        let vcToReturn: UIViewController

        if let navController = viewController as? UINavigationController {
            vcToReturn = UIViewController.getVisibleViewControllerFrom(navController.visibleViewController)
        }
        else if let tabBarController = viewController as? UITabBarController {
            vcToReturn = UIViewController.getVisibleViewControllerFrom(tabBarController.selectedViewController!)
        }
        else {
            if let presentedViewController = viewController.presentedViewController {
                vcToReturn = UIViewController.getVisibleViewControllerFrom(presentedViewController)
            }
            else {
                vcToReturn = viewController
            }
        }

        return vcToReturn
    }

}

You'd call this in the following way:

let visibleViewController = UIViewController.getVisibleViewController()

Hope this helps.

Andrew

PS I haven't tried this in Swift 2.0 yet, so I can't guarantee it will work without issues there. I know it won't work (as written) in Swift 1.1 or 1.0.

Big Red
  • 109
  • 1
  • 5