9

Through this question I would like to know if I understand well the notion of Root View Controller.

In iOS application, the Root View Controller (RVC) is the controller whose view gets added to the UIWindow application at startup, isn't true?

[window addSubview:rvcController.View];
[window makeKeyAndVisible];

Now, an UIWindow has also a rootViewController property. When running the previous snippet of code, does that property gets populated with the rvcController or do I have to set it explicitly?

Then, in a UINavigationController it is possible to set a RVC that is different from the previous RVC set for the entry point.

In this case, the first time I add a controller to the navigationController stack (pushing a new controller on it), does the framework set that controller as the RVC for the navigationController or do I have to set it explicitly through initWithRootViewController method?

Gajendra Rawat
  • 3,673
  • 2
  • 19
  • 36
Lorenzo B
  • 33,216
  • 24
  • 116
  • 190

4 Answers4

20

Ya.. when I began iPhone dev.. the rootViewController thing threw me for a loop too. But it’s really straight forward.

when the app starts, I create a UIWindow object in my app delegate class. Also, in that class, I have a property of type UIWindow called window;

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

    UIWindow *w = [[UIWindow alloc]initWithFrame:[[UIScreen mainScreen]bounds]];
    self.window=w;
    [w release];
    // other code here...
}

I then create a UIViewController whose view will be the first view in the window hierarchy, this could be called the "root view controller".

The confusing part is...that often we create a UINavigationController as the "root view controller" and that navigation controller has an init method that asks for a "RootViewController", which is the first viewcontroller it will place on its stack.

So, the window gets a "root view controller", which is the UINavigationController, which also has a RootViewController, which is the first view controller you want to show.

once you sort that out, its all makes sense.. I think :-)

here is some code that does it all.. (taken from a project I have open in front of me)

//called with the app first loads and runs.. does not fire on restarts while that app was in memory
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    


    //create the base window.. an ios thing
    UIWindow *w = [[UIWindow alloc]initWithFrame:[[UIScreen mainScreen]bounds]];
    self.window=w;
    [w release];

    // this is the home page from the user's perspective
    //the UINavController wraps around the MainViewController, or better said, the MainViewController is the root view controller
    MainViewController *vc = [[MainViewController alloc]init];

    UINavigationController *nc = [[UINavigationController alloc]initWithRootViewController:vc];
    self.navigationController=nc;  // I have a property on the app delegate that references the root view controller, which is my navigation controller.

    [nc release];
    [vc release];

    //show them
    [self.window addSubview:nc.view];
    [self.window makeKeyAndVisible];

    return YES;
}
Annika Backstrom
  • 13,937
  • 6
  • 46
  • 52
Jason Cragun
  • 3,233
  • 1
  • 26
  • 27
  • But this doesn't set window.rootViewController, does it? – nmr Aug 09 '12 at 15:41
  • the "relatively new" property window.rootViewController (as of 4.0) does add it to the window hierarchy and holds a reference to the windows root view controller. – Jason Cragun Aug 10 '12 at 01:50
  • Right, so, I don't see it being set, the VC is being added via `[self.window addSubview:nc.view];`, so this example would leave it unset, right? – nmr Aug 10 '12 at 15:10
  • Is the only change from a todays perspective (iOS 6) to call "window.rootViewController = nc" instead of "self.window addSubview:nc.view]" ? – Drazen Mar 29 '13 at 02:12
8

Now, an UIWindow has also a rootViewController property. When running the previous snippet of code, does that property gets populated with the rvcController or do I have to set it explicity?

You have to set it explicitly, and if you do, you can remove the addSubview line, because that's handled automatically when you set a root view controller.

Then, in a UINavigationController it is possible to set a RVC that is different from the previous RVC set for the entry point.

Of course, a navigation controller's root view controller has nothing to do with that of the window.

In this case, the first time I add a controller to the navigationController stack (pushing a new controller on it), does the framework set that controller as the RVC for the navigationController or do I have to set it explicity through initWithRootViewController method?

initWithRootViewController is just a shortcut for initializing an empty navigation controller and pushing the first (root) view controller onto the stack. Note that rootViewController is not a property of UINavigationController, you would access it via [navController.viewControllers objectAtIndex:0].

omz
  • 53,243
  • 5
  • 129
  • 141
  • Thank for your reply omz. What do you mean with _You have to set it explicitly, and if you do, you can remove the addSubview line, because that's handled automatically when you set a root view controller._? – Lorenzo B Apr 30 '11 at 14:12
  • Then, you said that `initWithRootViewController` is a shortcut method. Ok! So create a navigationController with this method or create a new one and push a controller on it, it is the same, Isn't true? Do both procedures create a root view controller that I'm not able to remove? – Lorenzo B Apr 30 '11 at 14:15
  • Thank you very much for your collaboration!! – Lorenzo B Apr 30 '11 at 14:15
  • 1
    The rootViewController property is not populated automatically if you add a subview to the window. You can remove the root view controller of a navigation controller, it's just the first element in an array that can be empty (though it should only temporarily be empty). – omz Apr 30 '11 at 15:27
  • Thank you very much omz. 2 more questions for you. **1)** Setting the rootViewController property for the UIWindow, it also allows to add the view to the window, it is ok? But if I don't set the rootViewController property, what happens? And once set, does the rootcontroller property for the window can be removed with another one? – Lorenzo B Apr 30 '11 at 16:25
  • **2)** So, it is possible to have a navigationController with no elements, it is ok? I was thinking that once set, the rootViewController (for a UINavigationController) couldn't be removed. So, do I have to think the rootViewController (in a UINavigationController) as the bottom element in the stack that is possible to remove? At this point, popToRootViewController method allows only to return to the first (the bottom element) in the stack, is it ok? Thank you again. You are very helpful!! – Lorenzo B Apr 30 '11 at 16:34
  • @omz You said that it is possible to remove the root view controller of a navigation controller. But in Apple doc there is written the following _The first item added to the stack becomes the root view controller and can never be removed._ Thank you again. Best regards. – Lorenzo B May 02 '11 at 07:35
  • Okay, seems I was wrong about this. Odd that this is not mentioned in the UINavigationController docs. I'd still assume that you could replace the root view controller, using -setViewControllers:animated:, but I've never needed this, so I haven't tried. – omz May 02 '11 at 12:06
1

firstly you can create A empty project in Xcode. after you add the new file on objectivec class view controller with xiv. now you can add to this code in appdeligate.m and set the rootviewcontroller in appdeligate

NOTE:- ViewController.h import to the appdeligate.m

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

// Override point for customization after application launch.
   self.window.backgroundColor = [UIColor whiteColor];

   ViewController *viewcontroller =[[ViewController alloc]initWithNibName:@"ViewController" bundle:nil];

self.window.rootViewController= viewcontroller;




 [self.window makeKeyAndVisible];
 return YES;

}

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

// Override point for customization after application launch.
   self.window.backgroundColor = [UIColor whiteColor];

   ViewController *viewcontroller =[[ViewController alloc]initWithNibName:@"ViewController" bundle:nil];

self.window.rootViewController= viewcontroller;




 [self.window makeKeyAndVisible];
 return YES;

}