390

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?

Cesare
  • 9,139
  • 16
  • 78
  • 130
ArtSabintsev
  • 5,170
  • 10
  • 41
  • 71
  • 5
    Do an NSLog of self.tabBarController right before you do the assignment. The message is only triggered if the controller is nil. If it is nil, and you've made sure your connections are correct, try instantiating the controller in the code. – FeifanZ Sep 25 '11 at 19:13
  • try to comment the initialization of the Window.. check this answer http://stackoverflow.com/a/33958144/1293445 – mohammad alabid Nov 30 '15 at 23:38

50 Answers50

442

Replace in AppDelegate

 [window addSubview:[someController view]];

to

  [self.window setRootViewController:someController];
OrdoDei
  • 1,379
  • 2
  • 16
  • 9
  • This got rid of the message for me. It is still not showing a subsequent window but that may be a different issue. Thanks. – Jazzmine Nov 25 '12 at 19:36
  • 4
    If you're using a UINavigationController you should first [[UINavigationController] initWithRootViewController:tableViewController] and then use the code above [self.window setRootViewController:self.navigationController] to set the window's root view controller – emdog4 Feb 17 '13 at 16:42
  • Cocos2d has a comment that says "// AddSubView doesn't work on iOS6 " So this fixed it for me, as I'm using iOS 6. – Almo May 13 '13 at 12:51
  • 1
    The `addSubview` line was a part of the project template on an early version of Xcode/iOS SDK. If the app goes back a long way, you may have it even if you didn't write it. – Seva Alekseyev Sep 11 '13 at 18:35
  • hello i am getting this eroor :- *** Assertion failure in -[UIApplication _runWithMainScene:transitionContext:completion:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit_Sim/UIKit-3505.16/UIApplication.m:3294 how to solve this – Akash Raghani Sep 22 '15 at 07:37
  • self.window.rootViewController = self.viewController; [self.window makeKeyAndVisible]; – jdl Jan 07 '16 at 19:31
  • This did not help. I simply had to connect the "rootViewController" outlet in the xib window to the navigationController. – Stiefel May 07 '17 at 20:23
189

I had this same problem. Check your main.m. The last argument should be set to the name of the class that implements the UIApplicationDelegate protocol.

retVal = UIApplicationMain(argc, argv, nil, @"AppDelegate");
sho
  • 741
  • 1
  • 7
  • 16
  • ack, nevermind, it didn't work :( Restarted iOS simulator, and bam, same problem. – ArtSabintsev Oct 12 '11 at 05:27
  • 49
    Another option is to make sure the app delegate class is imported in main and use `NSStringFromClass`. That's how Xcode now creates the main.m file. For example: `#import "AppDelegate.h` and then `int retVal = UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));` – sho Dec 21 '11 at 07:58
  • 10
    make sure `self.window` is initialized like `self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];` – Raptor Feb 13 '12 at 12:07
  • 1
    I tried the above options, didn't work for me. And I'm not using a Storyboard. – jowie May 16 '12 at 12:59
  • Thanks Shivan Raptor, I had to delete the line from my appDelegate didFinishLaunchingWithOptions method ;) – Bejil Jan 29 '13 at 23:02
  • 3
    Had no effect for me, same "Applications are expected ..." message after making the change. The solution was OrdoDei's answer (see above or below) which worked perfectly. – Andrew Feb 28 '13 at 19:36
  • 2
    If you see a white view in the Simulator but expected to see the layout from a storyboard make sure you got rid of the code in you root delegate function "application didFinishLaunchingWithOptions..." that's pointed at in main.m and only have "return YES;" in it. – Olivier de Jonge Jun 26 '14 at 11:01
  • hello iam stil getting error like this:- Assertion failure in -[UIApplication _runWithMainScene:transitionContext:completion:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit_Sim/UIKit-3505.16/UIApplication.m:3294 – Akash Raghani Sep 22 '15 at 07:34
70

I had the same error when trying to change the first view controller that was loaded in

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

At first I didn't really know where the error was coming from precisely so I narrowed it down and found out what went wrong. It turns out that I was trying to change the display of a view before it actually came on screen. The solution was hence to move this code in the viewcontroller that was giving me trouble from

- (void)viewDidLoad

to

- (void)viewDidAppear:(BOOL)animated

and the error stopped appearing. My problem specifically was caused by making a UIAlertView show.

In your case I suggest you check out the code in the tabBarController's active view controller (as it is probably a problem in that view controller). If that doesn't work, try to set the starting settings in the nib file instead of in code - or if you want to do it in code, try moving the code to the tabBarController's active viewcontroller's appropriate method.

Good luck!

RDM
  • 4,986
  • 4
  • 34
  • 43
  • 1
    Warkst, thanks for the answer. In my case, I can't move the code out of `viewDidLoad:` (without adding a flag), nor should I have to do this. Regardless, thanks for the suggestion! – ArtSabintsev Sep 23 '11 at 17:03
  • 2
    Found this today and glad I did - same issue - was showing an uialert a launch in viewDidLoad. Changed to viewDidAppear and works fine. Not sure what greater good Apple achieves by changing this in iOS5. – GuybrushThreepwood Oct 31 '11 at 17:14
  • Thanks for the suggestion that the alert view was causing it, that same problem happened to me too. – Chris Mar 11 '12 at 10:30
  • 1
    Could you tell us what code you had to remove in order to sort it out? I'm using my `viewDidLoad` for many things, setting up all the first-time stuff, such as adding data to the `UITableView`. I can't move it to `viewDidAppear:` because I only want it to fire once. – jowie May 16 '12 at 13:16
  • I had to specifically move the methods to alloc init and to display a `UIAlertView`. I guess if you only want to do those things once either, you could add a boolean guard to catch some kind of first-load behavior – RDM May 20 '12 at 18:47
  • 1
    The problem was not the wrong function. The problem was you were forgetting to call [super viewDidLoad] in your viewDidLoad function, effectively killing the nib load. The same thing has happened to me more than once. – borrrden Jun 05 '12 at 05:30
  • Thanks!!! I did something in the viewDidLoad, and move to the viewDidAppear, everything works fine... – flypig Jul 16 '12 at 09:20
  • Hey guys, I'm getting the same error as @Warkst and I've created the thread here, can anyone help me sort things out, please? http://stackoverflow.com/questions/14051129/application-windows-are-expected-to-have-a-root-view-controller-conditional-ap – Sergey Grischyov Dec 27 '12 at 07:56
  • hello i am getting this eroor :- *** Assertion failure in -[UIApplication _runWithMainScene:transitionContext:completion:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit_Sim/UIKit-3505.16/UIApplication.m:3294 how to solve this – Akash Raghani Sep 22 '15 at 07:37
47

I got this when starting with the "Empty Application" template and then manually adding a XIB. I solved it by setting the main Nib name as suggested by Sunny. The missing step in this scenario is removing

self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];

from

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

As it will overwrite the instance of your window created in the Xib file. This is assuming you have created a ViewController and wired it up with your window and App Delegate in the XIB file as well.

jlujan
  • 1,188
  • 7
  • 10
  • This fixed it for me too. I was using a Tabbed application with a Storyboard which I was trying to add CoreData to, and ran into this issue. – gitaarik May 24 '13 at 15:17
  • lol if I add this I get two warnings that Application windows are expected to have a root view controller!! – George Asda Dec 29 '13 at 11:29
46

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

Peter Johnson
  • 3,764
  • 1
  • 23
  • 27
arindam
  • 436
  • 2
  • 8
  • 16
  • 2
    This worked for me! This works when you create a empty project in Xcode 4.2, where no MainWindow will be present and this how we have to hook it up. – jeevangs Dec 14 '11 at 14:59
  • The problem for us happened when inadvertently we deleted the 'Main nib file base name' line from the 'Info.plist' file. Inserting this line again fixed the problem. – rtovars Jun 08 '12 at 17:15
  • You can also set this in the project properties. Select project, your target, you can edit this in Summary -> iPhone / iPad Deployment info. – doekman Jun 09 '13 at 09:41
  • this was actually the problem for me, leading to multiple issues dealing with calling viewDidLoad and viewWillAppear twice on the rootViewController. In my case removing this was the solution – whyoz May 05 '16 at 13:04
27

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.

Meet Doshi
  • 4,241
  • 10
  • 40
  • 81
denicija
  • 186
  • 2
  • 5
24

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;
    }
}
Daniel
  • 20,420
  • 10
  • 92
  • 149
Mike Flynn
  • 22,342
  • 54
  • 182
  • 341
23

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 {
RyeMAC3
  • 1,023
  • 1
  • 10
  • 17
20
  • 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
bearMountain
  • 3,950
  • 1
  • 36
  • 44
  • This is only found in Storyboard Mode, I think. – ArtSabintsev Nov 22 '11 at 21:03
  • Nope, this project was regular nib mode. [This](http://stackoverflow.com/q/7943489/888507) is a screenshot from Storyboard Mode. "Visible at Launch" vs. "Is Initial View Controller". – bearMountain Nov 23 '11 at 00:20
  • 3
    If the window nib file created manually, and "visible at Launch" is unchecked by default will prompt this message after app launch, this fix my problem! – ZYiOS Dec 08 '11 at 08:26
  • OH THANK YOU!!! Finally, a solution to this annoying warning. Even if you have `makeKeyAndVisible` it doesn't resolve the issue. ONLY this resolved the warning for me. THANK YOU! – tacos_tacos_tacos Feb 28 '12 at 02:44
  • 'This happens in regular nib mode - not storyboard mode` Not very true. I am facing the same issue with `Storyboard` also – geekay Sep 04 '12 at 06:59
  • @geekay_gk please see the link in my comment above - "Visible at Launch" does not show in Storyboard mode. – bearMountain Sep 04 '12 at 16:56
  • @bearMountain oh yes `Visible at Launch` is not available in storyboard. I thought you meant that the issue occurs only in nib. – geekay Sep 04 '12 at 18:21
  • @geekay_gk I see. I have edited the last line of my answer to clarify. – bearMountain Sep 04 '12 at 22:06
19

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,

rémy
  • 1,026
  • 13
  • 18
  • The cupsofcocoa.com article link is dead - any idea if there is a copy somewhere? – Ríomhaire Feb 24 '16 at 12:00
  • 1
    this has moved to binpress.com, updated the link in the answer – rémy Feb 24 '16 at 13:39
  • That's a great link. Good read and explains what is happening. I just encountered this issue as well using an old book (since I want to learn Objective-C first) but writing code on the latest XCode 7, which does not have the older templates. – ibaralf Jul 20 '16 at 20:58
11

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.

deepwinter
  • 4,568
  • 2
  • 31
  • 37
anticyclope
  • 1,577
  • 1
  • 10
  • 26
  • many kudos, this is what I wanted (empty project with storyboard) – Shtirlic Jan 04 '12 at 17:12
  • 2
    Same here. Thanks. If you create empty application, this method is filled with manual creation of the window. This should be changed to simply return YES. Thx – Ben G Feb 27 '12 at 18:49
11

I also had this error but unlike any of the answers previously listed mine was because i had uncommented the method 'loadView' in my newly generated controller (xcode 4.2, ios5).

 //Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView  
{
}

It even told me that the method was for creating the view programmatically but i missed it because it looked so similar to other methods like viewDidLoad that i normally use i didn't catch it.

To solve simply remove that method if you are not programmatically creating the view hierarchy aka using nib or storyboard.

trcarden
  • 881
  • 1
  • 9
  • 17
  • I can confirm that this can cause the issue. I had same situation by following the tutorial about TableView where they create set the delegates in loadView. After moving that code to viewDidLoad and removing the loadView, everything started to work as needed. – Eugen Dec 06 '11 at 05:39
  • You can still make use of load view but add [super loadView]; at its beginning. – Hermann Klecker Dec 23 '11 at 13:28
  • 1
    Hmm... the documentation for loadView specifically states that you should not call the super method. – Joshua Sullivan Dec 24 '11 at 19:02
  • I overrode the default UIViewController in a storyboard and found that the template code for creating a UIViewController subclass has loadView enabled by default causing this for me... wasted over an hour on this silly thing. Thanks for posting this! – slycrel Jan 27 '12 at 06:18
11

i got this problems too. i got my project run in xcode4.2.1. i've read all comments up there, but no one is cool for me. after a while, i find that i commented a piece of code.

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

then i uncommented it. everything is ok for me. hope this would helpful for you guys.

Bruce Lee
  • 4,177
  • 3
  • 28
  • 26
  • The code: "self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];" cause an error, so I just deleted it. – Grigori A. Dec 31 '12 at 12:33
10

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.

bobobobo
  • 64,917
  • 62
  • 258
  • 363
10

With my first view being MenuViewController I added:

MenuViewController *menuViewController = [[MenuViewController alloc]init];
self.window.rootViewController = menuViewController;

on the App Delegate method:

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

That worked.

Aziz Shaikh
  • 16,245
  • 11
  • 62
  • 79
cujino
  • 21
  • 2
9

Try to connect IBOutlet of tab bar controller to root view in the Interface Builder instead of

self.window.rootViewController = self.tabBarController;

But actually I haven't seen such error before.

d.lebedev
  • 2,305
  • 19
  • 27
8

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.

geekay
  • 1,655
  • 22
  • 31
8

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

RawMean
  • 8,374
  • 6
  • 55
  • 82
7

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.

CodeSmile
  • 64,284
  • 20
  • 132
  • 217
Raz
  • 1,387
  • 12
  • 13
  • that was exactly my problem! I had added a loadView implementation but didn't call super. Did some other code changes, couldn't remember what the heck I did. Got me stuck for 2 hours because that change seemed so innocuous. – CodeSmile May 16 '13 at 21:55
6

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.

Confused Vorlon
  • 9,659
  • 3
  • 46
  • 49
6

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;
}
Pétur Ingi Egilsson
  • 4,368
  • 5
  • 44
  • 72
6

I had this same error message in the log. I had a UIAlertView pop up in application:didFinishLaunchingWithOptions. I solved it by delaying the call to the alertView to allow time for the root view controller to finishing loading.

In application:didFinishLaunchingWithOptions:

[self performSelector:@selector(callPopUp) withObject:nil afterDelay:1.0];

which calls after 1 second:

- (void)callPopUp
{
    // call UIAlertView
}
janeway
  • 33
  • 2
  • 4
  • Thanks, this solved my problem. You must wait to show the alert until after the window is loaded. In my case I just did [alert performSelector:@selector(show) withObject:nil afterDelay:1.0]; – deepwinter Apr 03 '13 at 01:56
6

I had the same problem. If you're building a window-based application "from scratch" as I was, you'll need to do the following: (note, these are steps for Xcode 4.2.)

0. Make sure your application delegate conforms to the UIApplicationDelegate protocol.

For example, suppose our delegate is called MyAppDelegate. In MyAppDelegate.h, we should have something like this:

@interface MyAppDelegate : 
    NSObject <UIApplicationDelegate> // etc...

1. Specify the application delegate in main.m

For example,

#import "MyAppDelegate.h"

int main(int argc, char *argv[])
{
  @autoreleasepool {
    return UIApplicationMain(argc, argv,
      nil, NSStringFromClass([MyAppDelegate class]));
  }
}

2. Create a main window interface file.

To do this, right-click on your project and choose New File. From there, choose Window from the iOS -> User Interface section.

After adding the file to your project, go to the project's summary (left-click on the project; click summary.) Under iPhone/iPod Deployment Info (and the corresponding iPad section if you like) and select your new interface file in the "Main Interface" combo box.

3. Hook it all up in the interface editor

Select your interface file in the files list to bring up the interface editor.

Make sure the Utilities pane is open.

Add a new Object by dragging an Object from the Objects list in the Utilities pane to the space above of below your Window object. Select the object. Click on the Identity inspector in the Utilities pane. Change the Class to the application's delegate (MyAppDelegate, in this example.)

Bring up the connections inspector for MyAppDelegate. Connect the window outlet to the Window that already exists in the interface file.

Click on File's Owner on the left, and then click on the Identity inspector in the Utilities pane. Change the Class to UIApplication

Bring up the connections inspector for File's Owner. Connect the delegate outlet to the MyAppDelegate object.

4. Finally, and very importantly, click on the Window object in the interface file. Open the Attributes inspector. Make sure "Visible at Launch" is checked.

That's all I had to do to get it working for me. Good luck!

Tom
  • 18,685
  • 15
  • 71
  • 81
5

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;
}
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
4

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.

epx
  • 1,066
  • 9
  • 17
4

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;
    }
}
Kevin_TA
  • 4,575
  • 13
  • 48
  • 77
  • I'm curious to know how many windows your app had and if all had a root view controller. Thanks – DrAL3X Sep 28 '15 at 10:00
4

This occurred for me because i inadvertently commented out:

[self.window makeKeyAndVisible];

from

- (BOOL)application:(UIApplication*) didFinishLaunchingWithOptions:(NSDictionary*)
nicerobot
  • 9,145
  • 6
  • 42
  • 44
4

I was able to set the initial view controller on the summary screen of xcode.

Click on the top most project name in the left hand file explorer (it should have a little blueprint icon). In the center column click on your project name under 'TARGETS', (it should have a little pencil 'A' icon next to it). Look under 'iPhone / iPod Deployment Info' and look for 'Main Interface'. You should be able to select an option from the drop down.

RachelD
  • 4,072
  • 9
  • 40
  • 68
3

This issue happens when you don't have Interface Builder set up correctly.

Ensure your App Delegate's window and viewController outlets are hooked up:

In your MainWindow.xib, hold control, click App Delegate and drag to the Window object. Select window. Hold control and select the App delegate again, drag to your root view controller and select viewController.

uranazo
  • 11
  • 1
3

This error also show up when file's owner of MainWindow.xib is set incorrectly.

File's owner is UIApplication
->inserted object of app delegate class with window outlet connected to window

JakubKnejzlik
  • 6,363
  • 3
  • 40
  • 41
3

I was getting this error (Applications are expected to have a root view controller at the end of application launch), and I was creating the view controllers programmatically.

Solved it by ensuring the loadView method in my root view controller was calling [super loadView].

coco
  • 2,998
  • 1
  • 35
  • 58
  • Per the iOS 6.1 documentation for loadView, _“Your custom implementation of this method should not call super.”_  I think the preferred course of action is `self.view = [[UIView new] autorelease];`. – Slipp D. Thompson Apr 23 '13 at 14:26
1

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.

Kyle Parisi
  • 1,316
  • 1
  • 11
  • 14
1

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.

bneely
  • 9,083
  • 4
  • 38
  • 46
1

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.

Lisarien
  • 1,136
  • 1
  • 12
  • 24
1

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.

timthetoolman
  • 4,613
  • 1
  • 22
  • 22
1

Make sure that your "Is Initial View Controller" is correctly set for your first scene.enter image description here

That's what's causing the error.

Rasputin Jones
  • 1,427
  • 2
  • 16
  • 24
  • I don't seem to have that option anywhere. I see the exact same screen, sans the ***Initial Scene*** option. – ArtSabintsev Oct 31 '11 at 16:15
  • make sure your selecting the view controller. you can click on the top bar where the battery's displayed. if you've selected correctly the entire view controller will have a blue halo around it. – Rasputin Jones Nov 01 '11 at 02:20
1

This error hit me all of a sudden. So, what caused it?

It turns out I was in IB attaching File Owner to a new small ImageView I'd dragged onto the View. I hadn't called it an IBOutlet in the .h file, so when I ctrl-dragged to it, the new Imageview wasn't listed as a possible connection. The only possibility displayed in the little black box was View. I must have clicked, inadvertently. I made a few changes then ran the program and got the Root Controller error. The fix was reconnecting File Owner to the bottom View in the xib - IB screen.

Rob Smythe
  • 409
  • 1
  • 3
  • 16
0

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.

Zack Morris
  • 4,727
  • 2
  • 55
  • 83
0

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

user2387149
  • 1,219
  • 16
  • 28
0

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.

Megasaur
  • 626
  • 8
  • 20
0

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.

Sangram Shivankar
  • 3,535
  • 3
  • 26
  • 38
Noah Dyer
  • 407
  • 5
  • 10
0

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

Sangram Shivankar
  • 3,535
  • 3
  • 26
  • 38
greg
  • 1,926
  • 17
  • 26
0

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.

Jeff
  • 123
  • 5
0

This Swift 2 solution worked for me :

Insert the code below in AppDelegate -> didFinishLaunchingWithOptions

self.window!.rootViewController = storyboard.instantiateViewControllerWithIdentifier("YourRootViewController") as? YourRootViewControllerClass
SimpleJ
  • 13,812
  • 13
  • 53
  • 93
Fox5150
  • 2,180
  • 22
  • 24
0

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()
yoAlex5
  • 29,217
  • 8
  • 193
  • 205
0

I also had this problem. Turns out it was when I deleted the App Delegate from the Objects list on the left I deleted the connection for App Delegate, Window and TabBarController :)

Will Larche
  • 3,119
  • 7
  • 26
  • 34
0

Have you tried setting the delegate, i.e.

self.rootController.delegate = self;

within applicationDidFinishLaunchingWithOptions? That worked for me, although I'm not sure why.

beaudrykock
  • 248
  • 2
  • 17
0

for ARC change:

change to

@synthesize window;

instead of

@synthesize window=_window;
Manlio
  • 10,768
  • 9
  • 50
  • 79
Eric
  • 4,063
  • 2
  • 27
  • 49
0

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

- (void)applicationDidBecomeActive:(UIApplication *)application 

instead of

- (void)applicationWillEnterForeground:(UIApplication *)application
JScarry
  • 1,507
  • 1
  • 13
  • 25
-7

Validate your STORYBOARD file... If you are using IB to 'wire' code to your UI.. and just happen to delete the UI element ... and then realize, oh you need to delete the reference in the code (in my case a UIButton called AbortButton)... then moments later the app won't launch...

The issue is in the 'storyboard' file. Open it in an xml editor and look for orphaned 'relationships', of connectors which point places where they should not...

eg:

<relationships> <relationship kind="outlet" name="AbortButton" candidateClass="UIButton"/>

did NOT exist in my code anymore... (yet i still had a 'connector' linked up in the storyboard file)..

Also i had (somehow and invalid connector from a UIImageView or a ToolBar to my main UIViewController.view object)... don't think it liked that either...

bottom line - one doesn't have to manually 'code the controller' back into existence... the STORYBOARD file is whacked. I fixed mine, and bingo worked perfect again..

and BTW, as a text coder.. i am growing very fond of IB... kicks butt over MS Visual Studio's IDE...

Joe
  • 1