Being new to iOS development, I'm curious as to what might be the best approach for a situation where I need to branch from an initial UINavigationController to another UINavigationController depending on some condition. Say for example, when a user launches the app for the first time, I want to present the "create account" series of screens (I need to have more than one screen). But if they've already been activated, I want to be able to branch to another UINavigationController whose root view controller is the password entry screen which also has more screens after it. How do people do this kind of thing? I tried putting code in the main navigation controller's viewDidLoad() method and then calling performSegueWithIdentifier after I check the condition (e.g. does password exist), but when I segue, I get a blank screen because it's showing the other UINavigationController rather than the root controller it's pointing to. What am I doing wrong? I really don't have any code to show, just asking for an example or if there's preferred way to do this kind of thing.
3 Answers
On application launch, check if account has been created/logged-in, if so, create the Home navigation controller and set it as rootViewController
. If not, create CreateAccount navigation controller and set it as rootViewController
.
At the very end of account creation flow, you could present the Home navigation controller modally on top of CreateAcccount navigation controller. This is not much of an issue because, on next launch, you'll instantiate Home navigation controller only.
This is what I am talking about:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// ...
UIViewController *rootController = nil;
BOOL showCreateAccount = NO; // this should come from some storage e.g. NSUserDefaults
if(showCreateAccount == NO)
{
rootController = homeController; // create homeController
}
else
{
rootController = createAccountController; // create createAccountController
}
NSAssert(rootController, @"no user interface, what is this? a web service??");
self.window.rootViewController = rootController;
[self.window makeKeyAndVisible];
return YES;
}
If you really want to remove CreateAccount controller from view hierarchy and replace it with Home controller, you should create a custom segue. This Stackoverflow Question should get you started.
-
So this can't be in one storyboard? I see you're branching to storyboards, but I was assuming that it could be done easily in one by simple branching from a main nav controller to another, no? – u84six Jan 28 '16 at 20:56
-
using multiple storyboards is a good practice to keep separate interface flows separate, I have modified to code to remove references to storyboards. You can create these controllers however you want (whether in the same storyboard or in different storyboards or in Xibs) – ishaq Jan 28 '16 at 20:57
-
I want to be able to use navigation controllers because account creation and password entry has a series of screens that need back buttons, same navbar, style, etc. – u84six Jan 28 '16 at 21:00
-
that's exactly what I am saying. in the above example, I have assumed both the `createAccountController` and `homeController` are navigation controllers. what exactly is confusing? – ishaq Jan 28 '16 at 21:01
-
I've added a screenshot of the concept. Looks like this should be simple to do. How can I get it to work without having to swap root controllers like in your example?. The storyboard is allowing me to do it, so it must be possible. Reminder, this is in xcode 7 using swift. – u84six Jan 28 '16 at 21:09
-
In the screenshot, you have created a "Push" segue. Pushing a navigation controller is not supported, change the segue type to "Present Modally" and it will work. – ishaq Jan 28 '16 at 21:20
-
After changing the segue, it still shows up black (i.e. I think it's still trying to show the nav controller instead of the password view controller). I didn't really think that nav controllers can "show". – u84six Jan 28 '16 at 21:36
-
Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/101943/discussion-between-ishaq-and-u84six). – ishaq Jan 28 '16 at 21:37
-
Your solution worked, but I posted my final code in Swift vs OC. – u84six Jan 28 '16 at 22:56
You could do all of it in one VC. Create gesture recognizer for eg. swipe up & swipe down and then use switch-case for each separate setting. You can easily add a counter +1 for swipe up and -1 for swipe down, so you can even go back in the gesture recognizer.
The way you then make changes is by eg. giving your label new text in each case
switch swipeCounter {
case 1:
label.text = "do this"
funcForSomething()
default:
label.text = "do that"
funcForSomethingElse()
}
Here is a more full example that you might be able to use (Swift 2)
notice I declare the var upSwipes which then is used to check where in the sequence I am. See my screen shot of what "case 0" looks like.
var upSwipes = 0
override func viewDidLoad() {
super.viewDidLoad()
self.openingText.alpha = 0.0
self.swipeUp.alpha = 0.0
let swipeRight = UISwipeGestureRecognizer(target: self, action: "respondToSwipeGesture:")
swipeRight.direction = UISwipeGestureRecognizerDirection.Right
self.view.addGestureRecognizer(swipeRight)
let swipeUp = UISwipeGestureRecognizer(target: self, action: "respondToSwipeGesture:")
swipeUp.direction = UISwipeGestureRecognizerDirection.Up
self.view.addGestureRecognizer(swipeUp)
let swipeDown = UISwipeGestureRecognizer(target: self, action: "respondToSwipeGesture:")
swipeDown.direction = UISwipeGestureRecognizerDirection.Down
self.view.addGestureRecognizer(swipeDown)
}
func respondToSwipeGesture(gesture: UIGestureRecognizer) {
if let swipeGesture = gesture as? UISwipeGestureRecognizer {
switch swipeGesture.direction {
case UISwipeGestureRecognizerDirection.Down:
print("minus 1")
if upSwipes != 0 { upSwipes = upSwipes - 1}
case UISwipeGestureRecognizerDirection.Up:
print("plus 1")
upSwipes = upSwipes + 1
default: print("other direction")
}
switch upSwipes {
case 0:
self.openingText.alpha = 0.0
self.swipeUp.alpha = 0.0
self.openingText.text = "Swipe up, not down you silly "
self.openingText.alpha = 1.0
self.swipeUp.alpha = 1.0
case 1:
self.openingText.alpha = 0.0
self.swipeUp.alpha = 0.0
self.openingText.text = "Case specific text. Please swipe up again."
self.openingText.alpha = 1.0
self.swipeUp.alpha = 1.0
// Sequence to tell specifically why you need GPS permission and that in the next frame you will ask for it
case 2:
self.openingText.alpha = 0.0
self.swipeUp.alpha = 0.0
// initialAuthorization() // Your func to ask for GPS permission
// Sequence to ask eg. GPS use permission
case 3:
self.openingText.alpha = 0.0
self.swipeUp.alpha = 0.0
self.openingText.text = "Case specific text. Please swipe up again."
self.openingText.alpha = 1.0
self.swipeUp.alpha = 1.0
// Sequence to eg. ask name
case 4:
self.openingText.alpha = 0.0
self.swipeUp.alpha = 0.0
self.openingText.text = "Case specific text. Please swipe up again."
self.openingText.alpha = 1.0
self.swipeUp.alpha = 1.0
// Sequence to eg. send verification email
default:
self.openingText.alpha = 0.0
self.swipeUp.alpha = 0.0
let vc = storyboard?.instantiateViewControllerWithIdentifier("initilizing-done") as! InitializingDoneViewController
presentViewController(vc, animated: true, completion: nil)
// Then finally you might choose to go to other view controller. You need file (Cocoa class) with the same name InitializingDoneViewController.swift and VC whose specification will then be used for this VC that is modally shown herein.
}
}

- 157
- 1
- 9
This is how I got it to work in Swift:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
let activated = false || false
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let navController = activated ? "createAccount" : "enterPassword"
let navViewController = storyboard.instantiateViewControllerWithIdentifier(navController) as! UINavigationController
window?.rootViewController = navViewController
window?.makeKeyAndVisible()
return true
}

- 4,604
- 6
- 38
- 65