1

I started my project back in xcode 3 as "tabbed Application" in order to have a tab bar setup in Interface Builder.

Now I have good reasons to create my tab bar window programatically.

I have read lots of stuff and managed to create a new project with coded tab bar and all of that works fine. Therefore I believe that I understood how to create a tab bar project from scratch based on a new "Empty Application" (I think that was called "Window based application" in xcode 3).

However, when I try to adopt that code to my ongoing project that was started as "tabbed application" then I always get: "Applications are expected to have a root view controller at the end of application launch" on the debug console.

What do I have to do to change my project type from "tabbed application" to "empty application" retrospectively? Or is the only way to start a new project from scratch and copy all source files over from the old one?

BTW: googling the error message lead me to this excellent Thread: Applications are expected to have a root view controller at the end of application launch

Unfortunately none of the suggested solutions works for me. That is why I assume that my problem is related to the different types of projects from start.

Edit: I was asked to provide the didFinshWithLaunching code:

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

    [[UIApplication sharedApplication] setStatusBarStyle: UIStatusBarStyleBlackTranslucent];


#ifdef FREE

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

    self.tabBarController = [[[FcTabBarController alloc] init] autorelease];

    VotingMenuTVC *vc0  =[[[VotingMenuTVC alloc] initWithNibName:@"VotingMenuTVC" bundle:nil] autorelease];
    ChannelsTVC *vc1    =[[[ChannelsTVC alloc] initWithNibName:@"ChannelsTVC" bundle:nil] autorelease];

    NSArray* controllers = [NSArray arrayWithObjects:vc0, vc1, nil];
    tabBarController.viewControllers = controllers;


    // Add the tab bar controller's current view as a subview of the window
    float ver = [[[UIDevice currentDevice] systemVersion] floatValue];
    if (ver >= 4.0) {
        self.window.rootViewController = self.tabBarController;
    } else {
        [window addSubview:[tabBarController view]];
    }

    [window addSubview:[tabBarController view]];
    NSLog(@"RootViewController: %@",self.window.rootViewController);
    NSLog(@"TabBarController: %@",self.tabBarController);


#else   

    float ver = [[[UIDevice currentDevice] systemVersion] floatValue];
    if (ver >= 4.0) {
        self.window.rootViewController = self.tabBarController;
    } else {
          [window addSubview:[tabBarController view]];
    }

#endif

    [self.window makeKeyAndVisible];

    return YES;
}

For the current Target the compiler macro "FREE" was set. Otherwise it will compile for another targent for which the MainWindow.xib is still there (and works fine). Currently MainWindow.xib is still part of the Boundle, even the one for which FREE is set. But it is not set as main interface in the plist file for the target. The main interface is blank.

According to the NSLog statements (and debugging analyses) the toolBarController property is fine but the window's rootViewController is nil, which I don't understand.

As there has been a question from Firoze Lafeer asking wether MainWindow.xib still exists, that is the nex thing that I will change. I will update this post later depeding on the outcome.

Community
  • 1
  • 1
Hermann Klecker
  • 14,039
  • 5
  • 48
  • 71
  • Do you have a MainWindow nib still? Are the window and tab bar controller in there? What does your application:didFinishLaunchingWithOptions: look like? – Firoze Lafeer Dec 24 '11 at 01:33

2 Answers2

2

There is no need to start from scratch. If you are creating your UITabBarController in your app delegate, you need to make sure that you set it as the root view controller of your window. Since UITabBarController is a subclass of UIViewController, you can do this pretty easily!

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

    // Start creating your UITabBarController and set it up here:
    UITabBarController *tabBarController;
    // Finish creating your UITabBarController here

    self.window.rootViewController = tabBarController;

    [self.window makeKeyAndVisible];
    return YES;
}

It's probably best to make tabBarController a property too.

Luke Fletcher
  • 348
  • 2
  • 12
  • Thanks. That ist not it. I will add the didFinishWithLaunching code to the question. – Hermann Klecker Dec 24 '11 at 16:18
  • 1
    No, this IS it. Setting the root view controller property is now the preferred way of putting an initial view controller on screen. Adding a subview to the window is SO 2010. – Mark Adams Dec 24 '11 at 23:28
  • I'd agree with @MarkAdams. Adding a subview and autoreleasing it is lazy memory management anyway. – Jack Lawrence Dec 24 '11 at 23:54
0

The answer is ... I don't know. There was something else wrong within the project settings or plist or whatever.

Finally I ate it and started a new project from scratch. (Doning so I took the chance of identifying other bits and pieces that I found wrong, and I changed to ARC by that chance.)

So I copied all sources: *.h, *.m, *.xib, *.png but no plist etc. (I don't yet have any localized strings but if I had, then I had copied them as well of course) But I did not copy MainWindow.xib which I deleted from the original project anyway.

Finally the didFinishLanuchingWithOptions method is no surprise at all:

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

    [[UIApplication sharedApplication] setStatusBarStyle: UIStatusBarStyleBlackTranslucent];

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

    FcTabBarController *localTabBarConroller = [[FcTabBarController alloc] init];
    self.tabBarController = localTabBarConroller;

    NSArray* controllers;

    UserCentralVC *vc1  =[[UserCentralVC alloc] initWithNibName:@"UserCentralVC" bundle:nil user:nil userId:nil];
    ChannelsTVC *vc0    =[[ChannelsTVC alloc] initWithNibName:@"ChannelsTVC" bundle:nil] ;
    AppMenuTVC *vc3     =[[AppMenuTVC alloc] initWithNibName:@"VotingMenuTVC" bundle:nil] ;  //Re-Use another similar nib file. 

    UINavigationController* vnc0 = [[UINavigationController alloc] initWithRootViewController:vc0];
    UINavigationController* vnc1 = [[UINavigationController alloc] initWithRootViewController:vc1];
    UINavigationController* vnc3 = [[UINavigationController alloc] initWithRootViewController:vc3];

#ifdef FREE
    controllers = [NSArray arrayWithObjects:vnc0, vnc1, vnc3, nil];
#else   
    VotingMenuTVC *vc2  =[[VotingMenuTVC alloc] initWithNibName:@"VotingMenuTVC" bundle:nil] ;  
    UINavigationController* vnc2 = [[UINavigationController alloc] initWithRootViewController:vc2];
    controllers = [NSArray arrayWithObjects:vnc0, vnc1, vnc2, vnc3, nil];
#endif

    self.tabBarController.viewControllers = controllers;


    // Add the tab bar controller's current view as a subview of the window
    float ver = [[[UIDevice currentDevice] systemVersion] floatValue];
    if (ver >= 4.0) {
        self.window.rootViewController = self.tabBarController;
    } else {
        [self.window addSubview:[self.tabBarController view]];
    }

    [self.window makeKeyAndVisible];

    return YES;
}

Thanks to everybody who helped. Sometimes it is just helpful to talk about even if the solution is not directly presented on a silver plate :)

Seasonal greetings to all of you!

Hermann Klecker
  • 14,039
  • 5
  • 48
  • 71