View Hierarchy, UITabBarController, adding more views in certain tabs - iphone

So I'm not sure what is the best way to do something, or the preferred way. Here's essentially what we are trying to do:
-UITabBarController as the root
-first tab is a FruitViewController
-FruitViewController can push an AppleViewController (not sure if push is the correct word, but basically go to the next viewController)
-AppleViewController has a back button in the UIToolBar to return to FruitViewController
-second tab is VegetableViewController
-VegetableFruitViewController can push CeleryViewController
At the end of both ViewControllers, you can push another ViewController called CalorieViewController. My question is that what's the best way to present view controllers per tab? Since I want both tabs to use CalorieViewController, in order to reuse it, I'm assuming I need to keep it non-coupled with the other ViewControllers.
The way my coworker implemented is, on each tab, all ViewControllers for that tab are created and added as a subview. Based on the button pressed, it hides and shows the other view. This seems like not a good idea. It seems like presentModalViewController, and dismissModalViewController (for the back button) might work, but I'm not sure if that's the preferred method.

I would suggest you make the root view controller for each tab a UINavigationController, with the view controller's that are currently set for the tabs as the root view controller of the navigation controller. That way you can push and pop views all you want. UIViewController even has support for automatically pushing the tab bar off the screen when pushing a new view controller onto the stack.

Related

What is the proper way to create a segue to a new View without putting it on current UINavigationController's stack?

I'm trying to create an app using storyboard which has 4 scenes:
ChooseLoginMethod
EnterLoginData
SuccessfulLogin
MainScene.
What I'm doing right now is the following: I have an UINavigationController which has ChooseLoginMethod as its root view. ChooseLoginMethod has several buttons (for different login methods) which are push segues to EnterLoginData. EnterLoginData has a push segue to SuccesfullLogin and SucessfullLogin has a push segue to MainScene.
The problem is that SuccessfulLogin and MainScene display the back button on the top bar, which makes no sense for the application.
I've tried:
Hidding the top bar on these two Views. Not successful.
Changing the segue to modal. Seems to work, but doesn't feel like the right thing to do.
So what I would like to do is create a segue which breaks the chain of Views which are on the UINavigationController's stack. Is there a proper way to do this in storyboard?
-- edit --
Maybe what I should do is replace the root view ( Set root view for UINavigationController ). This may work, but seems like a programming work-around for something that should be possible to be done in storyboard. Or maybe it is just me not getting the "iOS way of doing stuff".
You had to use setNavigationBarHidden before the viewcontroller appears on the screen, like in viewWillAppear.
But then you can't go back from "MainScene" to the "RootController". So you should do something like popToRootViewController after "SuccessfulLogin" and then pop "MainScene".
I think it's usually best to have your main scene be the root view controller. From its viewDidAppear method, you can present your ChooseLoginMethod controller modally, and from there do modal transitions to your other login controllers. When you get to the end, and you want to go back to the main scene just dismiss the modals from the root view controller -- this will dismiss the first one, and any that were presented from it:
[self.view.window.rootViewController dismissViewControllerAnimated:YES completion:nil];

Unhide tabbar when a new view is pushed

I have UITableViewController embeded in a UINavigationController in my app. When a row is selected it pushes a UITabBarController. So far so good. The problem is that some of the tabs I push more views but the tab bar gets hiden. I've tried setting hidesBottomBarWhenPushed = NO, but it doesn't work.
I'm using XCode 4 with storyboard
Any ideas?
I've had this problem in one of my apps (though it was in iOS 4.x, using nibs not storyboard).
What I did to solve it: You want to have the root controller for each tab (the one with tabitem, etc) be a navigation controller - and when you push new views onto this navstack, they will respect the top navigation bar and bottom tab bar (they may actually display two navbars, so you have to be careful, but generally this is the way to go.)
first of all you might want to take a look at this
viewController: The view controller that is pushed onto the stack. It
cannot be an instance of tab bar controller.
so pushing an instance of tab bar controller is not recommended. There's a good reference there that might accomplish the task you wanted ill just provide the link here

Changing viewcontroller for a tab in a tabbar controller

I am currently developing an app that has a TabBarController and each of the tabs contains a navigation controller. This way on each tab I can show details of the rows selected on a view by pushing the viewcontroller to the navigation controller. Each of the views also have an UINavigationItem above them. In this navigation item I placed a button.
But now I would like to change the viewcontroller for a certain tab, when clicking the button in the UINavigationItem, BUT the view(controller) I want to change to has to act like the root view controller of that tab.
So I do not want to push another view on the navigation controller, but just switch to that view (in the same tab) and have that act as the root view controller.
I cannot find a good way to do this, with actually having the views work correctly. They either do not dealloc when I switch views (which would be nice, because I want to keep memory usage to a minimum).
One way of solving this, might be that I add more tabs to my TabBar Controller and just switch to the right tabs when I click the button, but that would be a last resort.
Not really sure if I described this correctly, but I was wondering what the best way is to do this. My preference is having 3 viewcontrollers and switch between them.
Hopefully I understand your question correctly: you want to basically 'reset' your navigation controller to have a new root.
You can do this by telling your navigation controller that you want to display a new set of view controllers:
[navigationController setViewControllers:[NSArray arrayWithObject:newViewController]
animated:NO];
This will get rid of all view controllers currently on that navigation controller's stack, and reset the root view to newViewController.

One UINavigationcontroller for the whole app?

i´ve created a UINavigationController in my appdelegate and initialized it with my "modelselectionViewController". This VC has different uibuttons and when touched, a new VC ("modelViewController") is pushed on the navigationstack.
This "modelViewController" acts as my template view and has a uitabbarcontroller with different tabs. The first VC is shown immediately but any changes on the navigationcontroller doesn´t work. I would like to set the name of the title but that navigationcontroller is null.
NSLog(#"navi: %#",
self.navigationController);
If i change my code to push the different VC when touching the different tabs, navigation works but only with a third level of navigation hierachy.
I want to know if it´s possible to use only one navigationcontroller for all my different tabs. Hope i made my setup clear. Appreciate all your help. thanks
I think you might want to read Combining ViewControllers.
In general, you should have the tabbar controller as a 'root' controller, not as a 'child' controller. A quick search in Apple's doc didn't yield a formal 'forbidden', but it might be.
If you create a UITabBarController from a view that's managed in a UINavigationController (ie: if you create a navigationcontroller first, and it's still around when you create the tabbarcontroller), you're starting a fight with the frameworks. Here's the admonishment from the docs on combining viewcontroller interfaces:
An application that uses a tab bar
controller can also use navigation
controllers in one or more tabs. When
combining these two types of view
controller in the same user interface,
the tab bar controller always acts as
the wrapper for the navigation
controllers. You never want to push a
tab bar controller onto the navigation
stack of a navigation controller.
Doing so creates an unusual situation
whereby the tab bar appears only while
a specific view controller is at the
top of the navigation stack. Tab bars
are designed to be persistent, and so
this transient approach can be
confusing to users.
I read that as "if it doesn't break something that we haven't thought of on the next update, we might reject the app anyway because it's 'confusing to users.'"
I suppose you could kill the whole navigation hierarchy and the navigationcontroller if you don't need to return there (like if you just used it for a one-time setup screen). Or you can look into other options for navigating within a viewcontroller that's managed by the navigationcontroller.
One thing to try might be to navigate to a UITableView, and use its cells to push a modal view onto the navigation stack. That would be familiar to users and also jive with the intent of the navigation classes.

What is the pattern for an Iphone app with both a View Controller and Tab Bar Controller?

I am trying to write an iPhone app that has both a UITabBar controller (and its associated views) and a plain vanilla view controller that is not part of the TabBar (i.e. an initial config page that only gets displayed the first time the app is run).
I am able to put a Tab Bar Controller and a View Controller in MainWindow.xib and shuffle between the two in the app delegate.
While this works I'm wondering if this is the best way to be implementing this.
It doesn't feel very "MVC-ish" to me but I think the two different controllers both need to be root (?)
I don't know how else I would do it.
If the config page is really only a "run once" affair, you could just pop it as a modal view from within the tab bar controller via the presentModalViewController:animated: method. (If on the other hand the config page is ever likely to be required in the future, I'd just add it as another option on the UITabBar.)
You would make the tabbarcontroller the default view. And present the viewcontroller modally in viewWillAppear or similar method. Then when you want to switch to the tabbar, you'd dismiss the modal view controller.