Get top most UIViewController

Zoyt picture Zoyt · Oct 31, 2014 · Viewed 160.9k times · Source

I can't seem to get the top most UIViewController without access to a UINavigationController. Here is what I have so far:

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

However, it does not seem to do anything. The keyWindow and rootViewController seem to be non-nil values too, so the optional chaining shouldn't be an issue.

NOTE: It is a bad idea to do something like this. It breaks the MVC pattern.

Answer

rickerbh picture rickerbh · Oct 31, 2014

presentViewController shows a view controller. It doesn't return a view controller. If you're not using a UINavigationController, you're probably looking for presentedViewController and you'll need to start at the root and iterate down through the presented views.

if var topController = UIApplication.sharedApplication().keyWindow?.rootViewController {
    while let presentedViewController = topController.presentedViewController {
        topController = presentedViewController
    }

    // topController should now be your topmost view controller
}

For Swift 3+:

if var topController = UIApplication.shared.keyWindow?.rootViewController {
    while let presentedViewController = topController.presentedViewController {
        topController = presentedViewController
    }

    // topController should now be your topmost view controller
}

For iOS 13+

let keyWindow = UIApplication.shared.windows.filter {$0.isKeyWindow}.first

if var topController = keyWindow?.rootViewController {
    while let presentedViewController = topController.presentedViewController {
        topController = presentedViewController
    }

// topController should now be your topmost view controller
}