ArtSabintsev
ArtSabintsev

Reputation: 5180

Applications are expected to have a root view controller at the end of application launch

I get the following error in my console:

Applications are expected to have a root view controller at the end of application launch

Below is my application:didFinishLaunchWithOptions method:

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

    // Set Background Color/Pattern
    self.window.backgroundColor = [UIColor blackColor];
    self.tabBarController.tabBar.backgroundColor = [UIColor clearColor];
    //self.window.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"testbg.png"]];

    // Set StatusBar Color
    [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackTranslucent];

    // Add the tab bar controller's current view as a subview of the window
    self.window.rootViewController = self.tabBarController;
    [self.window makeKeyAndVisible];
    return YES;
}

In Interface Builder, the UITabBarController's delegate is hooked up to the App Delegate.

Anyone know how to fix this issue?

Upvotes: 391

Views: 305455

Answers (30)

yoAlex5
yoAlex5

Reputation: 34175

I got such error when worked with CoreData with custom ServiceLocator

let context: NSManagedObjectContext = try self.dependencies.resolve()

//solution
let context: NSManagedObjectContext? = try? self.dependencies.resolve()

Upvotes: 0

Fox5150
Fox5150

Reputation: 2199

This Swift 2 solution worked for me :

Insert the code below in AppDelegate -> didFinishLaunchingWithOptions

self.window!.rootViewController = storyboard.instantiateViewControllerWithIdentifier("YourRootViewController") as? YourRootViewControllerClass

Upvotes: 0

denicija
denicija

Reputation: 186

I run into the same problem recently, when building a project with ios5 sdk. At first it was building and running properly, but after that the error appeared.
In my case the solution was rather simple.
What was missing, was that somehow the Main Interface property in the summary tab of my application target got erased. So I needed to set it again.


If this is not the point, and if the tabBarController is still nil, you can always programmatically create your window and root controller. As a fallback I added the following code to my project

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{ 
    if (!window && !navigationController) {
        NSLog(@"Window and navigation controller not loaded from nib. Will be created programatically.");
        self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
        UIViewController *viewController1, *viewController2;
        viewController1 = [[[FirstViewController alloc] initWithNibName:@"FirstViewController_iPhone" bundle:nil] autorelease];
        viewController2 = [[[SecondViewController alloc] initWithNibName:@"SecondViewController_iPhone" bundle:nil] autorelease];

        self.tabBarController = [[[UITabBarController alloc] init] autorelease];
        self.tabBarController.viewControllers = [NSArray arrayWithObjects:viewController1, viewController2, nil];
        self.window.rootViewController = self.tabBarController;

    }
    else {
        [window addSubview:[tabBarController view]];
    }
    [self.window makeKeyAndVisible];
    return YES;
}

This will work only if sho's solution is implemented also.

Upvotes: 27

greg
greg

Reputation: 2006

Moving setRootViewController: from didFinishLaunchingWithOptions: to awakeFromNib: solved this in my empty project.

Upvotes: 0

Noah Dyer
Noah Dyer

Reputation: 407

In my case, everything about the actual window and the didFinishLaunchingWithOptions: method was fine.

My error was that I didn't realize applicationDidBecomeActive: runs on startup in addition to when the app is coming to the foreground after having been in the background.

Therefore, in applicationDidBecomeActive: I was manipulating view controllers that hadn't finished all their setup yet (waiting for different threads to respond, etc).

Once I moved this functionality outside of applicationDidBecomeActive, the errors went away.

Upvotes: 0

rémy
rémy

Reputation: 1052

how to add a RootViewController for iOS5

if your app didn't use a RootViewController till now, just create one ;) by hitting File > New > New File; select UIViewController subclass name it RootViewController, uncheck the With XIB for user interface (assuming you already have one) and put this code in your AppDelegate :: didFinishLaunchingWithOptions

rootViewController = [[RootViewController alloc] init];
window.rootViewController = rootViewController;

for sure - you have to import RootViewController.h and create the variable

here is a nice article about the RootViewController and the AppDelegate,

Upvotes: 19

Mike Flynn
Mike Flynn

Reputation: 24325

I upgraded to iOS9 and started getting this error out of nowhere. I was able to fix it but adding the below code to - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

NSArray *windows = [[UIApplication sharedApplication] windows];
for(UIWindow *window in windows) {
    if(window.rootViewController == nil){
        UIViewController* vc = [[UIViewController alloc]initWithNibName:nil bundle:nil];
        window.rootViewController = vc;
    }
}

Upvotes: 24

Jeff
Jeff

Reputation: 123

If your app replaces the main UIWindow with FingerTipWindow (to show touches on a projector) and you haven't updated your sources for a few (several) years, your replacement object might not include a rootViewController property (see kgn's 5/21/2013 mod at GitHub)

You can set window.rootViewController in didFinishLaunchingWithOptions until the cows come home, but your window will not report one "at end of application launch" and will throw an exception at runtime. Update your sources.

Upvotes: 0

Kevin_TA
Kevin_TA

Reputation: 4675

To add to Mike Flynn's answer, since upgrading to Xcode 7 and running my app on an iOS 9 device, I added this to my (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

// Hide any window that isn't the main window
NSArray *windows = [[UIApplication sharedApplication] windows];
for (UIWindow *window in windows) {
    if (window != self.window) {
        window.hidden = YES;
    }
}

Upvotes: 4

Megasaur
Megasaur

Reputation: 626

None of the answer quite fixed my issue.

I am working on an old iOS4 project upgraded to ARC and now being worked on in Xcode 5 for iOS 7

I read through all of them and started checking my config and code.

What fixed it for me was adding

-(BOOL) application:(UIApplication*) application didFinishLaunchingWithOptions: (NSDictionary*) launchOptions
{
    // Maybe do something
    return YES;
}

In addition to having

- (void)applicationDidFinishLaunching:(UIApplication *)application
{
}

I did not have

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

prior to getting the error.

Upvotes: 0

user2387149
user2387149

Reputation: 1218

None of the above worked for me... found out something wrong with my init method on my appDelegate. If you are implementing the init method make sure you do it correctly

i had this:

- (id)init {
    if (!self) {
        self = [super init];
        sharedInstance = self;
    }
    return sharedInstance;
}

and changed it to this:

- (id)init {
    if (!self) {
        self = [super init];
    }
    sharedInstance = self;
    return sharedInstance;
}

where "sharedInstance" its a pointer to my appDelegate singleton

Upvotes: 0

Lisarien
Lisarien

Reputation: 1136

I had this error too but no answer already listed was solving my issue. In my case the log display was due to the fact I was assigning the application root view controller in another sub-thread.

-(BOOL) application:(UIApplication*) application didFinishLaunchingWithOptions:(NSDictionary*) launchOptions
{
    ...
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_async(queue, ^{
        ...
        dispatch_async(dispatch_get_main_queue(), ^{
            ...
            [self updateTabBarTitles];
            self.window.rootViewController = self.tabBarController;
            ...
        });
    });

    [self.window makeKeyAndVisible];
    return YES;
}

By moving the rootViewController assignment to the end of the function - just before the call to makeKeyAndVisible: - causes the log message not to be displayed again.

{
    ...
    self.window.rootViewController = self.tabBarController;
    [self.window makeKeyAndVisible];
    return YES;
}

I hope this helps.

Upvotes: 1

Pétur Ingi Egilsson
Pétur Ingi Egilsson

Reputation: 4442

Received the same error after replacing my UI with a Storyboard, using XCode 4.6.3 and iOS 6.1

Solved it by clearing out all of the code from didFinishLaucnhingWithOptions in the AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    return YES;
}

Upvotes: 6

Basil Bourque
Basil Bourque

Reputation: 338171

OrdoDei gave a correct and valuable answer. I'm adding this answer only to give an example of a didFinishLaunchingWithOptions method that uses his answer as well as accounting for the others’ comments regarding Navigation Controller.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

    // Override point for customization after application launch.

    // Instantiate the main menu view controller (UITableView with menu items).
    // Pass that view controller to the nav controller as the root of the nav stack.
    // This nav stack drives our *entire* app.
    UIViewController *viewController = [[XMMainMenuTableViewController alloc] init];
    self.navigationController = [[UINavigationController alloc] initWithRootViewController:viewController];

    // Instantiate the app's window. Then get the nav controller's view into that window, and onto the screen.
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // [self.window addSubview:self.navigationController.view];
    // The disabled line above was replaced by line below. Fixed Apple's complaint in log: Application windows are expected to have a root view controller at the end of application launch
    [self.window setRootViewController:self.navigationController];
    self.window.backgroundColor = [UIColor whiteColor];
    [self.window makeKeyAndVisible];
    return YES;
}

Upvotes: 5

bobobobo
bobobobo

Reputation: 67224

There was a slight change around iOS 5.0 or so, requiring you to have a root view controller. If your code is based off older sample code, such as GLES2Sample, then no root view controller was created in those code samples.

To fix (that GLES2Sample, for instance), right in applicationDidFinishLaunching, I create a root view controller and attach my glView to it.

- (void) applicationDidFinishLaunching:(UIApplication *)application
{
  // To make the 'Application windows are expected
  // to have a root view controller
  // at the end of application launch' warning go away,
  // you should have a rootviewcontroller,
  // but this app doesn't have one at all.
  window.rootViewController = [[UIViewController alloc] init];  // MAKE ONE
  window.rootViewController.view = glView; // MUST SET THIS UP OTHERWISE
  // THE ROOTVIEWCONTROLLER SEEMS TO INTERCEPT TOUCH EVENTS
}

That makes the warning go away, and doesn't really affect your app otherwise.

Upvotes: 10

Raz
Raz

Reputation: 1387

I began having this same issue right after upgrading to Xcode 4.3, and only when starting a project from scratch (i.e. create empty project, then create a UIViewController, and then Create a separate nib file).

After putting ALL the lines I used to, and ensuring I had the correct connections, I kept getting that error, and the nib file I was trying to load through the view controller (which was set as the rootController) never showed in the simulator.

I created a single view template through Xcode and compared it to my code and FINALLY found the problem!

Xcode 4.3 appears to add by default the method -(void)loadView; to the view controller implementation section. After carefully reading the comments inside it, it became clear what the problem was. The comment indicated to override loadView method if creating a view programmatically (and I'm paraphrasing), otherwise NOT to override loadView if using a nib. There was nothing else inside this method, so in affect I was overriding the method (and doing nothing) WHILE using a nib file, which gave the error.

The SOLUTION was to either completely remove the loadView method from the implementation section, or to call the parent method by adding [super loadView].

Removing it would be best if using a NIB file as adding any other code will in effect override it.

Upvotes: 7

epx
epx

Reputation: 1096

On top of "sho" answer, that is correct (fourth parameter of UIApplicationMain should be the name of the main controller), I add some comments.

I have recently changed the 'model' of an app of mine from using MainWindow.xib to construct a window programatically. The app used an older template that created that MainWindow automatically. Since I wanted to support a different controller view XIB for iPhone 5, it is easier to choose the right XIB programatically when the App Delegate is created. I removed MainWindow.xib from project as well.

Problem was, I forgot to fill the fourth parameter in UIApplication main and I FORGOT TO REMOVE MainWindow from "Main Interface" at Project Summary.

This caused a BIG problem: it rendered the harmless warning "Applications are expected to..." on development devices, but when it went to App Store, it broke on consumer phones, crashing because MainWindow was no longer in the bundle! I had to request an expedited review for the bugfix.

Another sympthom is that sometimes a white block, like a blank UIView, was sometimes appearing when Settings were changed and app was put in foreground. In iPhone 5 it was clear that it was an 320x480 block. Perhaps the missing MainWindow was being created in development mode, using the old size. I had just found this bug when the first reports of the crash reached the inbox.

Installing the app from App Store instead of from XCode showed that the app indeed crashed, and the MainWindow issue revealed itself on log, so I could see that it was not some special combination of devices+IOS versions.

Upvotes: 4

Zack Morris
Zack Morris

Reputation: 4823

I was migrating an old EAGLView sample project to the new GLKView sample project in Xcode 4 and none of the solutions worked for me. Finally I realized that I was trying to set the main GLKViewController's self.view to point to a nested GLKView in Interface Builder.

When I pointed the self.view back to the root GLKView in Interface Builder, my app was then able to launch without an error message (so make sure your view controller's view is set to the root view).

P.S. if you want to get a nested GLKView working, create a new member variable like self.glkSubview in ViewController.h and drag its connection to the nested GLKView in Interface Builder. Then make sure to drag self.glkSubview's delegate to File's Owner. You must manually call [self.glkSubview display] in "- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect" if you have setNeedsDisplay turned off for the GLKView.

Upvotes: 0

RyeMAC3
RyeMAC3

Reputation: 1023

None of the above suggestions solved my problem. Mine was this:

Add:

window.rootViewController = navigationController;

after:

[window addSubview:navigationController.view];

in my appdelegate's

- (void)applicationDidFinishLaunching:(UIApplication *)application {

Upvotes: 23

Confused Vorlon
Confused Vorlon

Reputation: 10426

If you use MTStatusBarOverlay, then you'll get this error.

MTStatusBarOverlay creates an additional window ([[UIApplication sharedApplication] windows) which doesn't have a root controller.

This doesn't seem to cause a problem.

Upvotes: 6

bneely
bneely

Reputation: 9093

I ran into this in an iPad application targeting iOS 5.1 in Xcode 4.5.1. The app uses UITabBarController. I needed a new section within the tab bar controller, so I created a new view controller and xib. Once I added the new view controller to the tab bar controller, none of my on-screen controls worked anymore, and I got the "expected to have a root view controller" log.

Somehow the top-level object in the new xib was UIWindow instead of UIView. When I dropped a UIView into the XIB, had the view outlet point to it, moved all the subviews into the new UIView, and removed the UIWindow instance, the problem was fixed.

Upvotes: 1

OrdoDei
OrdoDei

Reputation: 1429

Replace in AppDelegate

 [window addSubview:[someController view]];

to

  [self.window setRootViewController:someController];

Upvotes: 443

bearMountain
bearMountain

Reputation: 3980

  • Select your "Window" in your Nib File
  • In "Attributes Inspector" Check "Visible at Launch"

image![]

  • This happens when your nib file is created manually.
  • This fix works for regular nib mode - not storyboard mode

Upvotes: 20

Kyle Parisi
Kyle Parisi

Reputation: 1416

Although a lot of these answers seem valid, none of them fixed the message for me. I was experimenting with the empty application template and trying to load straight to a .xib file for understanding sake (like to old window template). It seems like Apple left an NSLog message running.

I was on Xcode 4.3 and nothing seemed to get rid of the message and I wanted to know why. Finally I decided to see what would happen in Xcode 4.5 (preview/iPhone 6.0 build) and the message is no longer there. Moving on.

Upvotes: 1

geekay
geekay

Reputation: 1673

I came across the same issue but I was using storyboard

Assigning my storyboard InitialViewController to my window's rootViewController.

In

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
...
UIStoryboard *stb = [UIStoryboard storyboardWithName:@"myStoryboard" bundle:nil];
self.window.rootViewController = [stb instantiateInitialViewController];
return YES;
}

and this solved the issue.

Upvotes: 8

timthetoolman
timthetoolman

Reputation: 4623

Sounds like self.tabBarController is returning nil. tabBarController probably is not wired up in Interface Builder. Set the IBOutlet of tabBarController to the tabBarController in Interface Builder.

Upvotes: 1

arindam
arindam

Reputation: 536

This happened to me. Solved by editing .plist file. Specify the Main nib file base name.(Should be MainWindow.xib). Hope this will help.

enter image description here

Upvotes: 46

anticyclope
anticyclope

Reputation: 1587

Make sure you have this function in your application delegate.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:    (NSDictionary *)launchOptions {
   return YES;
}

Make sure didFinishLaunchingWithOptions returns YES. If you happened to remove the 'return YES' line, this will cause the error. This error may be especially common with storyboard users.

Upvotes: 11

JScarry
JScarry

Reputation: 1507

I had the same error message because I called an alert in

- (void)applicationDidBecomeActive:(UIApplication *)application 

instead of

- (void)applicationWillEnterForeground:(UIApplication *)application

Upvotes: 0

RawMean
RawMean

Reputation: 8717

I solved the problem by doing the following (none of the other solutions above helped):

From the pulldown menu associated with "Main Interface" select another entry and then reselect "MainWindow" then rebuild.

enter image description here

Upvotes: 8

Related Questions