AppDelegate, rootViewController and presentViewController

how to present view controller in app delegate
present view controller from appdelegate - swift
present view controller on window swift
set root view controller programmatically swift 5
push to root view controller swift
get current view controller from appdelegate swift 4
get root view controller swift
change root view controller swift 5

I'm doing the Facebook integration tutorial, I want to show my MainViewViewController if the user has a valid token for the current state otherwise I want to show LoginViewController.


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    if (FBSession.activeSession.state == FBSessionStateCreatedTokenLoaded) {
        // To-do, show logged in view
    } else {
        // No, display the login page.
        [self showLoginView];
    return YES;
- (void)showLoginView
    UIStoryboard *mainstoryboard = [UIStoryboard storyboardWithName:@"MainStoryboard"          bundle:nil];
    LoginViewController* loginViewController = [mainstoryboard      instantiateViewControllerWithIdentifier:@"LoginViewController"];
    [self.window.rootViewController presentViewController:loginViewController animated:YES completion:NULL];

Console error :

Warning: Attempt to present <LoginViewController: 0xb492fd0> on <MainViewViewController: 0xb1bd820> whose view is not in the window hierarchy!

I don't want to use a NavigationController.

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];

Present view controller from app delegate, This will be the root view controller, that will be responsible for all cross-part transitions. So we let rootViewController = AppDelegate.shared. Swift - Access Different View Controllers in the Application Delegate In app delegate, with a simple app having only 2 screens: first screen is a Table View Controller embedded in Navigation Controller second screen is a View Controller which is used to add items to the first screen table via protocol/delegate/segue An

How to replace the `rootViewController` of the `UIWindow` in iOS, My AppDelegate.swift has the application funct: func a. the window with the SideNavigationViewController as the root view controller window� [[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:

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! ViewController

var 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)

iOS: Root Controller Navigation. How to switch between the , rootViewController presentViewController:[UIViewController new] animated:YES completion:nil]; will cause this exact warning (tested both on iOS6 & 7 Sim)� AppDelegate, rootViewController y presentViewController Estoy haciendo el Facebook de integración tutorial, quiero mostrar mi MainViewViewController si el usuario tiene un token válido para el estado actual de lo contrario, quiero mostrar LoginViewController.

In Swift 3 :-

let storyboard = UIStoryboard(name: "Login", bundle: nil)
let viewController = storyboard.instantiateViewController(withIdentifier: "LoginViewController")
window?.rootViewController?.present(viewController, animated: true, completion: nil)

presentViewController does not work: view is not in the window , rootViewController! if(vc is ViewController){ let storyboard = UIStoryboard(name: presentViewController(viewController, animated: false, completion: nil). It seems that rootViewController actually is of type UINavigationController in my case, so casting it on declaration allowed me to call pushToViewController directly on it.

In case, when you're not using a storyboard. First you need to create YourViewController. Go File -> New -> File... (or shortCut - command + N)

After that, choose Cocoa Touch Class. Click Next, or Enter

Than type name for your viewController and click Next

#import "AppDelegate.h"
#import "YourViewController.h"

@interface AppDelegate ()


@implementaion AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

// Init window
self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
[self.window makeKeyAndVisible];

// Init YourViewController
YourViewController *viewController = [[YourViewController alloc] init];

// Init YourNavigationController
UINavigationController *navigationContoller = [[UINavigationController alloc] initWithRootViewController: viewController];

// Set rootViewController
self.window.rootViewController = navigationContoller;

return YES;



Swift 3/4 Example

import UIKit


class AppDelegate: UIResponder, UIApplicationDelegate {

var window: UIWindow?

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

//1-st step
window = UIWindow(frame: UIScreen.main.bounds)

//2-nd - create a window root controller, and create a layout
let layout = UICollectionViewFlowLayout()
window?.rootViewController = UINavigationController(rootViewController: HomeController(collectionViewLayout: layout))

return true


AppDelegate, rootViewController and presentViewController , Now I am setting the rootViewController of my app's window object to a view controller I need to navigate. Below is a complete code example of how to go take� AppDelegate পদ্ধতি হ্যান্ডেল অ্যাকশন উইথ আইডেন্টিফায়ার থেকে একটি


ios - Present view controller from app delegate,

Is it possible to run a View Controller method within the AppDelegate?,

  • It works ! thanks ! I'm sorry but I don't have enough reputations to vote up your answer... I hope someone else will do that ;)
  • THANK YOU! Finally got the answer I needed :)
  • Thanks! I was about to quit on this ha!
  • Thanks, man!! I've spent a couple of hours to find this answer
  • I'm getting "Unbalanced calls to begin/end appearance transitions for <UINavigationController: 0x17564c30>"
  • Guys, please help, I have a same issue, but can't figure out what's going to be the Swift version? I do this: var sharedApplicationVC : UIViewController! = self.window?.rootViewController while var vvc = sharedApplicationVC.presentedViewController{ sharedApplicationVC = vvc } sharedApplicationVC.presentViewController(closeableVC, animated: true, completion: nil) , but it gives me memory leak issue: <UIKit/UIView.h> may also be helpful. fatal error: unexpectedly found nil while unwrapping an Optional value
  • does this work if there is uialertcontroller displaying on the screen and want to present another viewcontroller?
  • Thank you ! :) Saved my day :)
  • Yes! I've try all, but nothing works. This is the correct answer for me. Save my day! Thanks.
  • Why to use a while and not a simple If?, the If works better for me
  • This won't work unless the rootViewController is in the window hierarchy which isn't always the case. My app got a warning when I tried this.
  • @Brainware You can set root view controller in appDelegates didFinishLaunchingWithOptions function, for example : UIViewController *mainVC = [[MainVC alloc] initWithNibName:@"MainXB" bundle:nil]; [self setRootViewController:mainVC]; Or you can define a reference object for your rootViewController and change its value on different scenarios.
  • also, Check @Stepan-Generalov solution. I think its completely fine.