ios best practices- navigation and tab controllers and push/pop - iphone

My problem:
My app requires a user to be logged in, so the first view I show is a login view. If we are logged in, then we show the app view, which is a tab bar controller. One of these tabs is account info + logging out. On logging out, I want to go back to the the login screen.
My solution:
The root view is a navigation controller, which holds the main view. The main view is transparent, just says are you not logged in? Push the account screen onto the stack. If logged in, push the tab controller view onto the stack. Each tab in the tab controller is a navigation controller. Clicking on the account tab pushes the account view on the account view onto the stack. The account view has a logout button, which pops up 2 views (and doesn't work):
// Go to main view (2 views up) to show default login screen (as we won't be logged in anymore)
UINavigationController *navController = self.navigationController;
[navController popViewControllerAnimated:NO];
[navController popViewControllerAnimated:YES];
What I think is the problem:
The navigation controller that I have on the top level is not the same as the lower level navigation controllers in the tab controller.
My problem seems fairly typical, but my solution seems really clunky. This can't be the best way to do it! Any advice?

Try something like this? It seems convoluted but let's try it.
[self.navigationController popViewControllerAnimated: NO];
[self.tabBarController.navigationController popViewControllerAnimated: YES];

Related

How to present a login workflow? (modal and navigationController)

I currently need to present a login screen, followed by other screens before returning to the main menu.
Currently, I check if anyone is logged in on the main menu, and then present a modal login view (inside a UINavigationController) if not.
The user then fills in their login details and clicks submit. But before returning to the main menu (now logged in), I need to present two more screens to display some options.
I am not sure which structure to use for this. I thought about pushing the options screen onto the stack when the use clicks the submit button. However, Once they are done with that screen, and pop back to the root (login) view controller, is there any way to dismiss the modal view automatically, or should I structure this in another way?
Thanks.
You can push your login screen within a UINavigationController and use this controller to push your additional, post login screens.
// create and add your view controller to a navigation Controller
LoginController *loginController = [[LoginController alloc] init];
UINavigationController *navigationController = [UINavigationController alloc] initWithRootController:loginController];
// present it modally
[self presentViewController:navigationController animated:YES];
Once your user are done with the last of the post login screens, calling dismissViewController on the navigationController will go back to your main screens.
[self.navigationController dismissViewControllerAnimated:YES];
The best way to do so is to present it modally in your app delegate where you are using the navigation controller, just initialise your login view here and present it modally from your navigation controller like follows.
[self.navigationController presentModalViewController:loginView animated:yes];
and inside your loginview just use
[self.navigationController dismissViewController animated:YES];

Xcode - Logout button

Apparently, I have one LoginViewController and a StartUpController.
LoginViewController has functionality to authenticate user and register new user (presentModalViewController). Once the user has logged in, my system will display StartUpController.
Inside this StartUpController, I have everything such as TabBarController, NavigationController, etc. This StartUpController is actually handling 5 different views.
My question is: what should I do to remove all of my views when my user click on "LogOut" button from one of my view?
I want to show my LoginViewController again.. but at the same time, remove the StartUpController view and all its views.
Please teach me how to do this:
If your authentication view is your root view controller's view, use the -popToRootViewControllerAnimated: method on your navigation controller reference, e.g.:
[myNavigationController popToRootViewControllerAnimated:YES];
Assuming you're not doing any weirdness with view controller ownership, the navigation controller will release the children view controllers (which, in turn, should release their views and other properties).

iPhone Login -> tabbarcontroller

I have created an app and a login and would like to join them together with no luck. The app has a tabbarcontroller with navigationcontrollers via tableviewcells to drill down to other views of the app.
As I am having no luck in joining the two. I have tried to build on from the login that I have done. I can push to a new view but it does not show a tabbarcontroller etc on the next view. I have seen various forums with people having this problem as well.
So, my question: How can I make a new page (login) open to a TabBarController instead of a view (in the middle of my app, not at the launch)?
Does anyone out there know how to solve this issue?
Use navigation controller in tab bar controller. lets say the navigation controller is its first view controller. Now when the root view controller of the navigation is being displayed, you can see the tab bar. Now if you keep pushing new view controllers in this navigation controller, the tab bar wont hide itself.
However if you present some view controller modally, it would hide itself.
As far as login is concerned, i will check if user has logged in or not. if no, then i would set the root view controller of navigation controller as loginviewconroller else some home page.
I would check the if the user is logged in in the first viewController that get loaded.
From there I would present the loginViewController via the presentModalViewController method.
The use will not see the tabbar if you set the withAnimation:NO.
Now just dismiss the login viewcontroller when the use is logged in.
One could also send a notification that the is logged in, so that viewcontrollers can update them self for the no logged in user.

How to get all navigation controllers to root in tab bar?

I have an app which has three tabs in tab bar controller .Each tab bar item has a navigation controller and there is a log out button on first tab bar item.Now if i navigate into different naigation controllers and log out then all the navigation controllers remain in the same state for new user.I want all the navigation controleers to get to root when users logs out.
Try this:
for (UINavigationController *navController in myViewController.tabBarController.viewControllers) {
[navController popToRootViewControllerAnimated:NO];
}
i think your prob can be solved by writing a method for logging out and the method pops all the view controllers added to the root controller.when the user taps on the logout button all the view controllers should be popped and if needed call the action in all the three view controllers.
hope it would work..
jtbandes, your answer works really well, but what if I need to push the root view controller for only one tab? I don't want other tabs to be modifier, I just need to push the root view controller of one tab.

Designing an Application with different ViewControllers

after reading a lot of tutorials and threads here on stackoverflow there is one basic question left in my head.
The structure of my App should be the following:
MainMenu - fullscreen without a navigation bar but 2 buttons (button1 and button2)
Page1 - should appear by pressing button1 and should have a navigation bar at the top with a "back"-button to get back to the MainMenu.
Page2 - should appear by pressing button2 without a navigation bar at the top. Page2 should be a UISplitView. There must be a back button somewhere.
(I think this is where the problem starts, a UISplitView can't be presented modally, can it?)
You should be able to add subpages to Page1.
So how can I do that? I don't need executable code but just a hint on how the structure of my app should be. For example where to add the navigation controller, how the MainMenu looks like.
Thanks in advance!
Are you trying to create an Application for iPad?
Your Application's UI sems inconsistent being First View the only view without navigation Bar.
You will be using standard navigation to navigate to page1 from home page. So you will be adding a navigation Controller with Home View Controller as a Root View COntroller with hidden navigation bar.
eg.
-(void)applicationDidFinishLaunching:...
{
HomeViewController * hvc = [[HomeViewController alloc]init];
UInavigationController * nvc = [[UINavigationController alloc]initWithRootViewController:hvc];
nvc.navigationBar.hidden = YES;
[window addSubView:nvc.view];
}
Then on tap of first Button you will be pushing the Page1 View Controller
-(IBActtion)button1Pressed:(id)sender
{
Page1ViewCOntroller * p1vc = [[Page1ViewCOntroller alloc]init];
[self.navigationController pushViewCOntroller:p1vc animated:YES];
}
In viewWillAppear: method of Page1ViewController unhide the NavigationBar and hide it in the viewWillDisappear: method
Your Page 2 needs to be splitViewController.
Now about Split View, Apple says
The split view controller’s view should always be installed as the root view of your application window. You should never present a split view inside of a navigation or tab bar interface.
But as there is no "must" written in the above statement, and since its finally a View Controller in itselt, you should be able to add it on the window or another view.
Try to create a VIewController, with split VIew added on it, and like page1, push the View on the navigation Controller.