2

I have 3 viewcontroller/views at the root of my Application: LoginViewController, HomeViewController, and PlayViewcontroller

What I'm looking for is a good way to swap between these three based on state (eg: successfully logging in would result in the loginViewcontroller pinging its delegate [the rootviewcontroller] to remove itself and display the homeviewcontroller)

I seem to have a couple options here:

1.RootViewController is a UIViewController. It adds/removes subviews as needed.

[self.view addSubview:loginViewController.view];

2.RootViewController is a UIViewController. It presents/removes views modally as needed.

[self presentViewController:loginViewcontroller animated:NO completion:nil];

3.RootViewController is a UINavigationController. It pushes/pops stuff.

[self pushViewcontroller:loginViewController];

I have read that the first option is kinda working around the whole idea of what a viewcontroller is supposed to be, and therefore not ideal.

The second option seems odd because my entire application is a modal? Can viewcontrollers be modally presented on top of modally presented viewcontrollers?

The third option seems best, (as stated here), but it runs into a few problems with my specific implementation:

  • the metaphor for the "navigationController" doesn't exactly fit (I'm not "drilling down into the home controller" by logging in...)
  • Do I constantly switch out the navController's rootviewcontroller? Or do I just push playvc on top of homevc on top of loginvc?
  • LoginVC is a navigationViewController in itself- it pushes on vc's that go through the multi-step process of creating an account, and I can't push navcontrollers on navcontrollers.

So, my question is this:

What is the best way to architect view controllers at equal level of hierarchy when some of them are UINavigationControllers themselves?

****Note:*** I have already looked here, but it didn't give sufficent answers for my use case (multiple navcontrollers).*******


EDIT: I've found an answer: I'm thinking of the problem wrong, and should instead be thinking in terms of creating my own Container ViewController.

1
  • view-controller containment is typically used for creating controllers akin to UINavigationController, UITabBarController, UISplitViewController - that is, a general purpose container for other specific-purpose controllers. Sure, it can be used for other purposes, but unless you have a good argument for why you'd use containment in this specific case, I'd advise against it. A good argument might be "I want my reusable signin-controller to be fully embedded in a subview of root page controller's view". But that's not what you indicated originally ("a way to swap between these ...") Commented May 6, 2013 at 23:19

3 Answers 3

2

I think you should consider a combination of 2 and 3. Since login is a one time thing in a session, it would be best not to have those controllers alive all the time -- better to use them, and then have them go away. To do this, I would make the root view controller of the window be a navigation controller with HomeViewController as its root, with a push transition to PlayViewController. LoginViewController should be presented modally, from the viewDidAppear method in HomeViewController so it will appear when the app first opens (if you have animation turned off). It's ok to present a navigation controller modally, it will cover up your root navigation controller, so you won't see two navigation bars.

Sign up to request clarification or add additional context in comments.

Comments

2

Can viewcontrollers be modally presented on top of modally presented viewcontrollers?

Yes.

I wouldn't think of your root controller as being presented modally. The root controller is owned by your application window. You can't dismiss it like you dismiss a modally-presented controller.

IMO, just present your login controller as a modal view controller and dismiss it once the user has successfully authenticated.

2 Comments

Ok... so I have it set up with my RootViewController (UIViewController) as the window's rootViewController, and I want it to "present" my loginViewController as soon as the app starts. Is it weird that it is only displaying when I put "[self presentViewController:loginViewController ...]" in viewDidAppear? (if I put it in viewDidLoad or viewWillAppear it doesn't display...) Does this mean that I need to be doing all my presenting/removing in viewDidAppear? That seems odd... Thoughts?
@Phildo - present will only work from a controller that is displaying it's own view, so this is normal. You could try in viewWillAppear:, and it might work, I think.
0

I had the same problem today, then I re-built a UITabBarController to understand that point (UITabBarController is built with Container viewcontroller including several navigationcontroller). I just added the code here https://github.com/damienromito/CustomTabBarController

The Apple docs about this are here : https://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/CreatingCustomContainerViewControllers/CreatingCustomContainerViewControllers.html

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.