How to skip 2 views when using navigation controller

ios, iphone, objective-c, uinavigationcontroller

Solution

In a nutshell, the most straightforward solution is to use `-[UINavigationController setViewControllers:animated:]`.

You need to do the following to achieve what you want:

- assign storyboard IDs to all your controllers,

- instantiate all three view controller from the story board (this is lightweight as long as you don't do most of the initialisation work in controller's constructors)

- put them into an array in the same order you have them in storyboard,

- call `-[UINavigationController setViewControllers:]` with the array as the first argument.

That's it. The code in your `-[AppDelegate application:didFinishLaunchingWithOptions:]` might look like this (after checking your skipping condition of course):

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
UIViewController *vc1 = [storyboard instantiateViewControllerWithIdentifier:@"MyAuth"]; //if you assigned this ID is storyboard
UIViewController *vc2 = [storyboard instantiateViewControllerWithIdentifier:@"Login"];  //if you assigned this ID is storyboard
UIViewController *vc3 = [storyboard instantiateViewControllerWithIdentifier:@"Details"];
NSArray *controllers = @[vc1, vc2, vc3];
UINavigationController *navController = (UINavigationController *)self.window.rootViewController;
[navController setViewControllers:controllers];

If you paste just this to `-[AppDelegate application:didFinishLaunchingWithOptions:]`, you'll see that it works immediately.

Problem

In Xcode 5.0.2 I've created an iPhone app (the complete app code is on GitHub, please run `pod install` once - for `SDWebImage`), which displays a list of social networks (Facebook, Google+, etc.), then - in another view - an `UIWebView` displaying OAuth2 web page and then a third view with user avatar and details (first name, last name, etc.): (Here the fullscreen screenshot of the storyboard shown above) Before I display the user avatar and details in the last view, I save the user data to `NSUserDefaults`. My question is: when the user starts the app the next time and there is user data in `NSUserDefaults` already - how can I skip the first 2 views and display (without any animation) the last view with those user details? I've put the following code to the AppDelegate.m: ``` - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; NSString *key = [defaults objectForKey:@"key"]; User *user = [User loadForKey:key]; if (user) { UINavigationController *nc = (UINavigationController*)self.window.rootViewController; // XXX how to load the last view here? XXX } return YES; } ``` and can see, that the user data is being loaded okay, but I don't understand how to jump to the last view (esp. because most of the UI is defined in the storyboard)? UPDATE: I have tried following Tommy Alexander's suggestion (thanks!) with the following code in AppDelegate.m (and also assigned `Details` StoryboardID to the last view): ``` - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; NSString *key = [defaults objectForKey:@"key"]; User *user = [User loadForKey:key]; if (user) { UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil]; UIViewController *uvc = [storyboard instantiateViewControllerWithIdentifier:@"Details"]; NSLog(@"XXX uvc=%@ user=%@", uvc, user); [self.window.rootViewController presentViewController:uvc animated:YES completion:nil]; } return YES; } ``` and while the last view (the UserViewController with user avatar and details) seems to be instantiated okay, I get the following warning and the app doesn't jump to the last view: ``` MyAuth[3917:70b] XXX uvc=<UserViewController: 0x8acbac0> user= VK 59751265 Alexander Farber 1945522 http://cs319319.vk.me/v319319265/b7df/TnyKeffL_mU.jpg 0 MyAuth[3917:70b] Warning: Attempt to present <UserViewController: 0x8acbac0> on <UINavigationController: 0x8bb3a30> whose view is not in the window hierarchy! ``` UPDATE 2: When I move the above code to the `viewDidLoad` of the 1st view (the MasterViewController.m, where the user can select a social network), then I get another warning: ``` MyAuth[1358:70b] XXX uvc=<UserViewController: 0x8a97430> user= FB 597287941 Alexander Farber Bochum, Germany http://graph.facebook.com/597287941/picture?type=large 0 MyAuth[1358:70b] Unbalanced calls to begin/end appearance transitions for <UINavigationController: 0x8a893e0>. ``` UPDATE 3: Thanks for the valuable answers! I've ended up using Leonty Deriglazov suggestion: ``` - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil]; UIViewController *vc1 = [storyboard instantiateViewControllerWithIdentifier:@"Master"]; //UIViewController *vc2 = [storyboard instantiateViewControllerWithIdentifier:@"Login"]; UIViewController *vc3 = [storyboard instantiateViewControllerWithIdentifier:@"User"]; User *user = [User load]; NSArray *controllers = (user ? @[vc1, vc3] : @[vc1]); UINavigationController *nc = (UINavigationController *)self.window.rootViewController; [nc setViewControllers:controllers]; return YES; } ```

Original source

Related problems