iosobjective-cmodel-view-controlleruiview-hierarchy

Root View Controller's view not in the Window Hierarchy


I have coded a login page which in my app delegate (under the method application:didFinishLaunchingWithOptions:) is set to be my root view controller with

[self.window setRootViewController:vc];

Where vc is the instantiation of my HomeVC.
This view loads correctly. I can enter in all of the data required for login just fine but as soon as I try and load another view I get

Warning: Attempt to present <RegisterVC: 0x7d07f520> on 
         <HomeVC: 0x7d374830> whose view is not in the window hierarchy!

I tried a little hack to be certain I got the top most view controller using the following code:

- (UIViewController*) topMostController
{
    UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController;

    while (topController.presentedViewController) {
        topController = topController.presentedViewController;
    }

    return topController;
}

but, as I suspected, it only ever returned the current view controller, which is also the root view controller. It never even enters the while loop.

I cannot understand how the view controller I'm trying to call from is not on the hierarchy when it's not only displaying correctly but is also the only view on the hierarchy at all.

Edit 1: I'll include the AppDelegate application:didFinishLaunchingWithOptions: method's section where I create and add the VC and the Navigation VC.

    UIViewController *vc = (HomeVC *)[[HomeVC alloc] initWithNibName:NSStringFromClass([HomeVC class]) bundle:nil];
    self.navigationController = [[UINavigationController alloc] initWithRootViewController:vc];
    [self.navigationController setNavigationBarHidden:YES];

    [self.window setRootViewController:vc];
    //^^^This is the line I'm most suspicious of, is that correct?^^^
    [self.window setBackgroundColor:[UIColor colorWithHexString:kDefaultBackgroundColor]];
    [self.window makeKeyAndVisible];

Solution

  • you can get the root view controller of the window, which should be the navigation controller, and then get its top view controller.

    try like this:if you are sure there is a viewController.presentedViewController then send includeModal as YES.

    - (UIViewController *)topmostViewControllerFrom:(UIViewController *)viewController
                                   includeModal:(BOOL)includeModal
    {
        if ([viewController respondsToSelector:@selector(selectedViewController)])
        return [self topmostViewControllerFrom:[(id)viewController selectedViewController]
                                  includeModal:includeModal];
    
        if (includeModal && viewController.presentedViewController)
        return [self topmostViewControllerFrom:viewController.presentedViewController
                                  includeModal:includeModal];
    
        if ([viewController respondsToSelector:@selector(topViewController)])
        return [self topmostViewControllerFrom:[(id)viewController topViewController]
                                  includeModal:includeModal];
    
        return viewController;
    }