How to get root view controller?

Objective CSwiftIos5UiviewcontrollerUinavigationcontroller

Objective C Problem Overview


I need an instance of root view controller.

I tried those approaches:

UIViewController *rootViewController = (UIViewController*)[[[UIApplication sharedApplication] keyWindow] rootViewController];

Returns: null:

Also when I try to get an array of controllers:

NSArray *viewControllers = self.navigationController.viewControllers;

It returns only one controller, but it isn't my root view controller.

If I try to take from navigation controller:

UIViewController *root = (UIViewController*)[self.navigationController.viewControllers objectAtIndex:0];

Returns: null:

Any ideas why? What else could I try to get an instance of my root view controller?

Thanks.

Objective C Solutions


Solution 1 - Objective C

if you are trying to access the rootViewController you set in your appDelegate. try this:

Objective-C

YourViewController *rootController = (YourViewController*)[[(YourAppDelegate*)
                                   [[UIApplication sharedApplication]delegate] window] rootViewController];

Swift

let appDelegate  = UIApplication.sharedApplication().delegate as AppDelegate
let viewController = appDelegate.window!.rootViewController as YourViewController

Swift 3

let appDelegate  = UIApplication.shared.delegate as! AppDelegate
let viewController = appDelegate.window!.rootViewController as! YourViewController

Swift 4 & 4.2

let viewController = UIApplication.shared.keyWindow!.rootViewController as! YourViewController

Swift 5 & 5.1 & 5.2

let viewController = UIApplication.shared.windows.first!.rootViewController as! YourViewController

Solution 2 - Objective C

Objective-C

UIViewController *controller = [UIApplication sharedApplication].keyWindow.rootViewController;

Swift 2.0

let viewController = UIApplication.sharedApplication().keyWindow?.rootViewController

Swift 5

let viewController = UIApplication.shared.keyWindow?.rootViewController

Solution 3 - Objective C

As suggested here by @0x7fffffff, if you have UINavigationController it can be easier to do:

YourViewController *rootController =
    (YourViewController *)
        [self.navigationController.viewControllers objectAtIndex: 0];

The code in the answer above returns UINavigation controller (if you have it) and if this is what you need, you can use self.navigationController.

Solution 4 - Objective C

For Swift 5 and later, I recommend use this method:

UIApplication.shared.windows.last?.rootViewController

Use .last will return top view Controller is active.

.first sometimes doesn't work with libraries that require a window on top & actived.

For example: Admob . I have the ad not showing and find that I am calling the hidden window underneath when using sheet or fullscreenCover.

NOTE: View want to display ads required in NavigationView, if not, ads will be not run.

Example: NavigationView { View1() }

I hope it is useful.

Solution 5 - Objective C

Unless you have a good reason, in your root controller do this:

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(onTheEvent:)
                                             name:@"ABCMyEvent"
                                           object:nil];

And when you want to notify it:

[[NSNotificationCenter defaultCenter] postNotificationName:@"ABCMyEvent"
                                                object:self];                

Solution 6 - Objective C

Swift 3

let rootViewController = UIApplication.shared.keyWindow?.rootViewController

Solution 7 - Objective C

Swift way to do it, you can call this from anywhere, it returns optional so watch out about that:

/// EZSwiftExtensions - Gives you the VC on top so you can easily push your popups
var topMostVC: UIViewController? {
    var presentedVC = UIApplication.sharedApplication().keyWindow?.rootViewController
    while let pVC = presentedVC?.presentedViewController {
        presentedVC = pVC
    }
    
    if presentedVC == nil {
        print("EZSwiftExtensions Error: You don't have any views set. You may be calling them in viewDidLoad. Try viewDidAppear instead.")
    }
    return presentedVC
}

Its included as a standard function in:

https://github.com/goktugyil/EZSwiftExtensions

Solution 8 - Objective C

Swift 3: Chage ViewController withOut Segue and send AnyObject Use: Identity MainPageViewController on target ViewController

let mainPage = self.storyboard?.instantiateViewController(withIdentifier: "MainPageViewController") as! MainPageViewController

var mainPageNav = UINavigationController(rootViewController: mainPage)
    
self.present(mainPageNav, animated: true, completion: nil)
 

or if you want to Change View Controller and send Data

let mainPage = self.storyboard?.instantiateViewController(withIdentifier: "MainPageViewController") as! MainPageViewController

let dataToSend = "**Any String**" or  var ObjectToSend:**AnyObject** 

mainPage.getData = dataToSend 

var mainPageNav = UINavigationController(rootViewController: mainPage)
    
self.present(mainPageNav, animated: true, completion: nil)  



                               

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionStreetboyView Question on Stackoverflow
Solution 1 - Objective CjanusfidelView Answer on Stackoverflow
Solution 2 - Objective CChamath JeevanView Answer on Stackoverflow
Solution 3 - Objective CespView Answer on Stackoverflow
Solution 4 - Objective CThiên QuangView Answer on Stackoverflow
Solution 5 - Objective CwistyView Answer on Stackoverflow
Solution 6 - Objective CcybermachView Answer on Stackoverflow
Solution 7 - Objective CEsqarrouthView Answer on Stackoverflow
Solution 8 - Objective Cuser6857463View Answer on Stackoverflow