2

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];
Matthew Bahr
  • 337
  • 1
  • 15
  • What's the result of `[UIApplication sharedApplication].window.rootViewController` ? (you'll have to cast it to your UIApplicationDelegate's type) – chedabob Dec 31 '15 at 00:36
  • Also it won't hit that while loop because `presentedViewController` is for VCs that are presented modally (which yours is not) via `presentViewController:animated:completion:` – chedabob Dec 31 '15 at 00:38
  • I'm getting an error when attempting to compile your code, do you mean keyWindow instead of window? Because `AppDelegate * app = (AppDelegate *)[UIApplication sharedApplication].window.rootViewController` just ends up with an error saying "Property 'window' not found on object of type UIApplication *". If you meant keyWindow you'll notice that in my hack I actually use that exact code to get the top controller, which is what I end up returning. For that loop what _should_ I use to make it work? – Matthew Bahr Dec 31 '15 at 03:26
  • Or should I make a dummy "root view controller" style class that just adds this HomeVC rather than having the root be the home view controller? – Matthew Bahr Dec 31 '15 at 03:34
  • @MatthewBahr How you are loading the another view, from HomeVC? – Avinash Tag Dec 31 '15 at 04:36
  • @AvanishTag Yes, the HomeVC has a button, Register in this case, which then loads the register view controller. Except this happens. – Matthew Bahr Dec 31 '15 at 05:39

1 Answers1

0

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;
}
Parth Bhatt
  • 19,381
  • 28
  • 133
  • 216
ShaluRaj
  • 67
  • 6
  • Ok so having tried that none of the if statements evaluate true and it just returns the viewController passed in. Was worth a shot though. – Matthew Bahr Dec 31 '15 at 05:44
  • This warning usually comes in Storyboards when it tries to perform 2 segues at the same time. I believe in appdelegate you are trying to present 2 viewcontrollers at the same time. – ShaluRaj Dec 31 '15 at 05:48
  • have you tried setting the navigation controller as the rootviewcontroller,[self.window setRootViewController:_navigationController]; – ShaluRaj Dec 31 '15 at 05:49