Using UINavigationController view - ios

I would like to better understand the use of UINavigationController's.
I have setup a new project with a UINavigationViewController, as well as two other view controllers.
In my app delegate I have the following:
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];
firstViewController = [[NCTFirstViewController alloc] initWithNibName:#"NCTFirstViewController" bundle:nil];
navController = [[NCTNavViewController alloc] initWithRootViewController:firstViewController];
self.window.rootViewController = self.navController;
[self.window makeKeyAndVisible];
Within my UINavigationController.m file I can set the title and set up buttons, but this does not work.
This only works if I setup the self.navigtionController items in the actual View Controller itself. Is this correct, or is there something I should be doing in the UINavigationController to get this to work.
Ideally I am looking for a UINavigationController that handles all the pushing to other controllers. In the long run it would be used as a menu system. So if the user clicks a button at the top, they are pushed to a new View Controller but without the back option, simply the same menu items in the navigation bar at the top, which shows a new center view controller.
The issue I am having is understanding how this is setup. If I have to setup this in the view controllers itself, would they all not duplicate the same code. Of course I could setup all the 'movement' in the AppDelegate, but this doesn't seem correct and would pack up the App Delegate itself.

If you look at the UINavigationController class reference, it says (emphasis added by me, but you should read it all so that you understand how this works):
Updating the Navigation Bar
When the user changes the top-level view
controller, whether by pushing or popping a view controller or
changing the contents of the navigation stack directly, the navigation
controller updates the navigation bar accordingly. Specifically, the
navigation controller updates the bar button items displayed in each
of the three navigation bar positions: left, middle, and right. Bar
button items are instances of the UIBarButtonItem class. You can
create items with custom content or create standard system items
depending on your needs. For more information about how to create bar
button items, see UIBarButtonItem Class Reference.
The bar button item on the left side of the navigation bar allows for
navigation back to the previous view controller on the navigation
stack. The navigation controller updates the left side of the
navigation bar as follows:
If the new top-level view controller has a custom left bar button
item, that item is displayed. To specify a custom left bar button
item, set the leftBarButtonItem property of the view controller’s
navigation item.
If the top-level view controller does not have a
custom left bar button item, but the navigation item of the previous
view controller has a valid item in its backBarButtonItem property,
the navigation bar displays that item.
If a custom bar button item is
not specified by either of the view controllers, a default back button
is used and its title is set to the value of the title property of the
previous view controller—that is, the view controller one level down
on the stack. (If there is only one view controller on the navigation
stack, no back button is displayed.)
The navigation controller updates
the middle of the navigation bar as follows:
If the new top-level view controller has a custom title view, the
navigation bar displays that view in place of the default title view.
To specify a custom title view, set the titleView property of the view
controller’s navigation item.
If no custom title view is set, the
navigation bar displays a label containing the view controller’s
default title. The string for this label is usually obtained from the
title property of the view controller itself. If you want to display a
different title than the one associated with the view controller, set
the title property of the view controller’s navigation item instead.
The navigation controller updates the right side of the navigation bar
as follows:
If the new top-level view controller has a custom right bar button
item, that item is displayed. To specify a custom right bar button
item, set the rightBarButtonItem property of the view controller’s
navigation item.
If no custom right bar button item is specified, the
navigation bar displays nothing on the right side of the bar.
The
navigation controller updates the navigation bar each time the top
view controller changes. Thus, these changes occur each time a view
controller is pushed onto the stack or popped from it. When you
animate a push or pop operation, the navigation controller similarly
animates the change in navigation bar content.
So, to do what you want, you do need to set the title and buttons in each view controller. The easiest way to set the title is to set it in the storyboard/xib, or in code when you create it.
You should also replace the root view controller instead of pushing the view controller onto the navigation stack so that you don't keep adding view controllers to the stack. This also avoids displaying the back button, and you won't need to explicitly get rid of it. You would do this by using the setViewControllers:animated: method like this:
[self.navigationController setViewControllers:[NSArray arrayWithObject:theNewViewController] animated:YES];

There is only one NavigationController and this NavigationController controls all the ViewControllers. So barButtonItems and titles are set in each ViewController, you should not set them directly to a NavigationController.
If you want to push a new ViewController and won't push back, I think this may cause some problem because the NavigationController is using a Stack to handle all the ViewControllers. Seems that you will push a ViewController in the stack but not pop it, and maybe you will get some behavior you don't want.
If you still want to implement this, I think you cannot avoid do similar setting in different ViewControllers.

Related

Model View Controller segue not showing UINavigationBar

I am trying to setup a Model View Controller to have a Navigation Bar just in the storyboard.
I have setup a segue from one view controller to another and marked it as Model.
I have changed the Model VC to have Top Bar : Translucent Navigation Bar.
I call the segue by name with the following:
[self performSegueWithIdentifier:#"testModel" sender:self];
When the model view controller shows up there is no Navigation Bar. Am I missing something that should make this show.
The Model View Controller is not actually in a Navigation Controller stack and shouldn't be as there is no movement other than dismiss from this Model View Controller. I am just trying to use the Navigation Bar to show a title for the model VC.
When you changed your view controller to "Top Bar : Translucent Navigation Bar.", that is under "Simulated Metrics". Changing that value tells Xcode that the view controller will have a navigation bar, it does not actually create a navigation bar. I suggest you either
Embed your view controller in a navigation controller (there is no rule that says you have to push anything from your navigation controller, and you might decide to add features in the future)
Use a toolbar instead of a navigation bar
Just use a label if all you want is a title on your view controller.

How do you change views from a Tab Bar Controller

I am developing an app that consists of a Tab Bar Controller that points to 3 view controllers (all with tabs). In one of these tab views I've made a button and I want it to open a new view (without a tab at the bottom). This new view would need a navigation bar with a back button to return to the previous view, so I was thinking I need to create a navigation controller?
Essentially this is what I'm trying to do (I apologize for the poorly drawn diagram).
How can I get this new view (entirely independent of the tab bar controller) to display programatically? Would this require a navigation controller?
You are describing a presented view controller. Call presentViewController:animated:completion:.
I very frequently do this with a navigation bar and a Back or Done button, just as you describe. But it's not a navigation controller or navigation interface; it's just a convenient way of showing the user how to get back.
For example, this is a presented view in one of my apps. The top is a navigation bar, and the cancel button gets us back (call dismissViewController...). The rest is a scrolling view (a UICollectionView) of buttons.
[myTabBar setSelectedIndex:1]
You may have to access the tabBar like self.tabBarController so… [self.tabBarController setSelectedIndex:1];
1 is index 1 in the tabbar's stack (this is like tapping a tabBar button manually)

what UINavigationController do with object which calls pushViewController: function?

Is it removes object from superview or just hides that object?
Check the docs :) Its adding it to the stack, not removing it. popViewControllerAnimated: removes it.
The object in the viewController parameter becomes the top view
controller on the navigation stack. Pushing a view controller results
in the display of the view it manages. How that view is displayed is
determined by the animated parameter. If the animated parameter is
YES, the view is animated into position; otherwise, the view is simply
displayed in place. The view is automatically resized to fit between
the navigation bar and toolbar (if present) before it is displayed.
In addition to displaying the view associated with the new view
controller at the top of the stack, this method also updates the
navigation bar and tool bar accordingly. In iOS 3.0 and later, the
contents of the built-in navigation toolbar are updated to reflect the
toolbar items of the new view controller. For information on how the
navigation bar is updated, see “Updating the Navigation Bar.”
http://developer.apple.com/library/ios/documentation/uikit/reference/UINavigationController_Class/Reference/Reference.html#//apple_ref/occ/instm/UINavigationController/pushViewController:animated:

Using splitviewcontroller with storyboards?

I have created a splitview controller in a storyboard that has a navigation bar across the top. I also have a master view with a tableview that when selected displays the correct view in the detail view controller.
How can I update the splitview controller's navigation bar title? I know I can access the master's nav bar through "self.navigationItem.rightBarButtonItem" but how do I access the main nav bar from this file?
Thanks
If you have a navigation bar across the top, then you can set the title like this:
self.title = #"this is my title";
If your title is fixed and doesn't change, then just add that line in your viewDidLoad method or where ever you would setup items in your view.
If you are trying to set the title programmatically, then it depends on which view controller you are in when you try to set the title. In the example above, it will set it for the view controller you are in.
If you want to set the opposite view controller navigation bar, you have a couple of ways to choose from depending on when you want to update it.
Generally though you would reference the opposite view controller directly using a delegate or indirectly using the splitViewController.viewControllers array.
it sounds like you already have a reference to the detail view controller. If so and you want to change its title from the master you can do so like this:
[self.detailViewController setTitle:#"New Title"];
hope that helps,
be well

Hidden UINavigationController inside UITabBarController

I have an application with 5 UIViewControllers each inside a corresponding UINavigationController, all tucked inside a UITabBarController that displays 5 tabs at the bottom of the screen.
I want to display another UIViewController (inside a UINavigationController) when a dialog button is pressed.
This view should only be loaded and unloaded programatically; i.e. it should not appear in the tab bar. However, I want the tab bar to be visible always.
If I add the [UINavigationController view] to [self window] the UITabBar is covered. If I add it to any other layer, the UINavigationController adds on the compensation it has for the status bar so appears further down than expected.
A solution would be to have the 6th UINavigationController added to the UITabBar with the others, but with its tabBarItem hidden. Then I can show it and hide it using the tabBars selectedIndex property.
Accessing the tabBarItem through the UIViewController shows no obvious way of doing this.
#wisequark, I think you completely misunderstood and you have almost rewritten the architecture of my application. However I have a separate navigation controller for each view as they are mutually exclusive and there is no concept of "drilling down".
#Kendall, This is what I expect I will have to do - have the modal view appear with a hide button to bring back the normal interface. But it would be nice to keep the tab bar always visible, so I was just wondering if anyone knew of a way.
It sounds as though you have a mess on your hands. A UINavigationController is a distinct object that is very different from a UITabBarController. In general, your application should have a tab controller, one of who's tab's loads a UINavigationController which in turn loads it's views - not that both maintain management over the different views. It is also improper to refer to the display of a UIViewController as such an object doesn't have a visual representation. In the case of a UINavigationController, the navigation controller object is responsible for displaying a navigation bar and a table view (in the most common case) and for managing the display of all the views in the navigation hierarchy. It itself has no corresponding representation on screen. Similarly, a UITabBarController presents a tab bar and is responsible for the loading and unloading of the views and/or view controllers attached to the tab buttons. If we were to present this as an image, it would look something like this -
alt text http://img.skitch.com/20081112-2sqp7q4wafa34te1ga337u4k8.png
Well, it sounds like what you really want to do is present a modal view with the tab bar still visible. You could add your view as a subview of the tab bar controller's view. The tab bar's view is, oddly enough, not the tab bar itself but rather a view containing the tab bar and the selected item's view.
Alternatively, you could try calling presentModalViewController:animated: with the selected tab (i.e. [tabBarController.selectedViewController presentModalViewController:animated:]) as the receiver instead of the tab bar. I seem to recall doing this once (quite by accident) and the tab bar remained visible.
One more thought: since each of your five view controllers is a UINavigationController, you could always pushViewController:animated: onto the selected view controller, then hide the back button. Your view will just appear without animation. But you'll need to remember to pop your view controller off the stack whenever the user switches to another tab. That might take a bit more work.
The best idea I could think of would be to either push a modal navigation controller for your view (which would hide the tab bar which you do not want), or to get the tab bar controller current selected view controller (really your navigation controller for a tab) and push your new view controller on there - and then pop that view when another tab is selected with a tab bar delegate.
It seems wierd to me to push the view onto random tabs though, if the view is created from a dialog that is modal, I don't see why the view itself should not also be modal and hide tabs.

Resources