15

I have an application that uses the "navigation-based application" template in XCode.

Now I want to change it so that the first view that loads is a regular (custom) UIView, and if the user clicks a particular button, I push the original RootViewController onto the NavigationController.

I understand that somewhere, someone is calling this with my RootViewController:

- (id)initWithRootViewController:(UIViewController *)rootViewController

I want to know how to replace the argument with my new class.

iter
  • 4,171
  • 8
  • 35
  • 59

3 Answers3

23

if you want to replace the root view controller of your navigation stack you can replace the first object of its view controllers array as -

NSMutableArray *viewControllers = [NSMutableArray arrayWithArray:[self.navigationController viewControllers]];

NewViewController *nvc = [[NewViewController alloc] init];
[viewControllers replaceObjectAtIndex:0 withObject:nvc];
[self.navigationController setViewControllers:viewControllers];
saadnib
  • 11,145
  • 2
  • 33
  • 54
  • This is an interesting idea. I like it better than what I'm doing now, but see my comment about magic in ljkyser's answer. – iter Apr 29 '11 at 19:19
  • Have you ever tried this? You cannot cast a NSArray with a NSMutableArray! You must create a NSMutableArray with [self.navigationController.viewControllers mutableCopy]. – DreamOfMirrors Dec 22 '11 at 09:21
5

^ These are all ways to do it programmatically. Thats cool. But I use the interface builder and storyboards in Xcode, so this is the easy and fast way to add a new view controller:

  • Open the storyboard in question
  • Add a new view controller to your storyboard by dragging it from the objects list (right hand tool bar bottom)
  • While holding down the CONTROL key, click and drag from the middle of your navigation controller (should be blank and gray) to your new fresh white view.
  • On the popup, selection Relation Segue: Root View Controller (should be below the normal push/modal/custom options you have likely seen before)

Tada! Enjoy your new root view controller without holding your day up with programmatic creation.

woody121
  • 358
  • 3
  • 14
  • Just because you prefer programmatic creation, doesn't mean you should downvote this answer. This works just fine. – woody121 Mar 01 '14 at 05:36
  • 5
    But the OP was asking about "Replacing" the RootViewController after a button click, so this is not the answer to the question. – Frederic Yesid Peña Sánchez Mar 27 '14 at 15:40
  • 1
    @woody121 this stackoverflow page was top google search result for xcode / interface builder method to change root view controller. your answer worked perfect, thank you! – tmr Apr 05 '15 at 03:54
2

Look inside the main app delegate .m file and find the method

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

Inside it will be a line like this

self.window.rootViewController = self.navigationController;

You can instantiate a diffent view controller there and assign it to be the rootViewController

ljkyser
  • 999
  • 5
  • 9
  • This is what I'm doing. I am noticing that the stock `didFinishLaunching` does not instantiate navigationController. I am curious who does and where, and how I can interject. Nominally, what I'm trying to avoid is doing the work twice (i.e. instantiating and immediately discarding a navigation controller). Really, I am trying to understand the behind-the-scenes magic that is XIB. – iter Apr 29 '11 at 19:17
  • 2
    It's actually stored in the MainWindow.xib file and is loaded lazily out of there I believe. I would think you could change the default it is using through interface builder, but I haven't done that before. We almost always do everything from code without interface builder, so we avoid that altogether. – ljkyser Apr 29 '11 at 21:24
  • Yeah, I almost always do everything from code, too. This is an older project--a legacy of the learning curve. – iter May 02 '11 at 01:28