AppDelegate, rootViewController and presentViewController AppDelegate, rootViewController and presentViewController xcode xcode

AppDelegate, rootViewController and presentViewController


I had the same issue. Based on the answer to this question, I added [self.window makeKeyAndVisible] just before presentViewController:animated:completion:, and that fixed it for me.

In your case, showLoginView becomes

- (void)showLoginView{    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];    LoginViewController *loginViewController = [storyboard instantiateViewControllerWithIdentifier:@"LoginViewController"];    [self.window makeKeyAndVisible];    [self.window.rootViewController presentViewController:loginViewController animated:YES completion:NULL];}


Sometimes presenting modal view controller from window.rootViewController may produce the same warning & have no effect.Example of such hierarchy of view controllers:

  1. [MYUITableViewController] (presented modally by MYUIViewController )
  2. [MYUIViewController] (rootViewController of UINavigationController below)
  3. [UINavigationController] (root)

Now calling

[[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:[UIViewController new] animated:YES completion:nil];

will cause this exact warning (tested both on iOS6 & 7 Sim)

Solution:Instead of using rootViewController - use the top one presented by it:

    UIViewController *topRootViewController = [UIApplication sharedApplication].keyWindow.rootViewController;    while (topRootViewController.presentedViewController)     {        topRootViewController = topRootViewController.presentedViewController;    }    [topRootViewController presentViewController:yourController animated:YES completion:nil];
  • Sometimes keyWindow may have been replaced by window with nil rootViewController (showing UIAlertViews, UIActionSheets on iPhone, etc), in that case you should use UIView's window property.


Stepan Generalov's answer was the right one for me in Swift 3!!!
Of course with the new syntax etc. so I'll copy it in here:

let sb = UIStoryboard(name: "Main", bundle: nil)let vc = sb.instantiateViewController(withIdentifier: "MainApp") as! ViewControllervar topRootViewController: UIViewController = (UIApplication.shared.keyWindow?.rootViewController)!while((topRootViewController.presentedViewController) != nil){    topRootViewController = topRootViewController.presentedViewController!}topRootViewController.present(vc, animated: true, completion: nil)

"MainApp" is my main view controller's identifier in this case.

I know there are other ways but if you need to have different URL schemes for opening different parts of your App, you must handle it in AppDelegate so this is perfect because in the

func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {}

method, you can just check what url is as a String and then decide if you execute the above written code or maybe a similar one with a different identifier for an other view controller (withIdentifier)