Chapter 9
UINavigationBar and UINavigationController

Key Skills & Concepts

• Understanding UINavigationBar, UINavigationController, and UINavigationItem

• Understanding how to use a navigation bar in a simple application

• Understanding how to programmatically manipulate a navigation bar’s items

• Adding a navigation bar to a tab in a tabbed application

A navigation bar is displayed along a window’s top, just below the status bar. The navigation bar optionally contains a title for each view displayed and one or more buttons. Typically, the button on the bar’s right, when clicked, takes the user to the next step in another view, although sometimes applications use the right button as a “done” button. The button on the bar’s left is a Back button, returning to the previous view. Navigation bars are often used with tables, where a table is displayed with a navigation bar above it. When a user clicks a table’s rows, the navigation bar’s associated navigation controller takes the user to more detailed information about the selected item. For instance, the App Store application allows a user to refine his or her categories until the application of interest is found (Figure 9-1). For instance, if a user clicked Games, the navigation controller would take the user to a Games subcategory. If the user then clicked All Games, the navigation controller would take the user to a table of all games in the App Store. If a user wished to go back a step, he or she would press the button on the navigation bar’s upper-left area. This button is the Back button. Note the navigation controller labeled the button’s title with the previous view’s title.

The navigation bar and navigation controller are useful for applications requiring hierarchical navigation, such as data drill-down. In the App Store application, you drill down to increasingly specific categories until reaching a list of items rather than further subcategories. When you select an item, it takes you to a more detailed view of your selection. Navigation bars are also useful for applications with multiple steps in a single task. In this chapter, you learn how to use a navigation bar and its associated classes. In the first task, you start with a Window-based application and manually create an application consisting of three views managed by a navigation controller. In the second task, you look at how the Utility Application template uses a navigation bar. This template uses a navigation bar on only one view and without using an associated navigation controller. Finally, this chapter presents a navigation controller embedded in a tab bar’s tab. This is perhaps this chapter’s most useful task and should not be skipped. You will find embedding a navigation controller in a tab a ubiquitous requirement when developing iOS applications.

Image

Image

Figure 9-1 Using the App Store application

UINavigationBar, UINavigationController, and UINavigationItem

Below the status bar but above the application window’s content, many applications have a navigation bar. Navigation bars display the current view’s title and contain one or more buttons for navigating to other screens. In this chapter’s introduction, you viewed the App Store application, a typical use for a navigation bar. The Notes application also uses a navigation bar (Figure 9-2). The navigation bar appears above the yellow notepad. Upon clicking the + key, the navigation bar displays a new note page. The navigation bar’s title is New Note and contains a back button labeled “Notes” and a right button labeled “Done.” When the user taps either button, the application returns the user to the application’s primary page.

You add navigation bars to an application using the UINavigationBar class, but you almost never use a UINavigationBar class directly. Instead you’ll use UINavigationBar’s controller, UINavigationController. You control a UINavigationBar using a UINavigationController. A UINavigationController uses a stack data structure to manage one or more view controllers. The first view controller, or the root view controller, is the first item on the stack. To navigate to other views, you push the view’s view controller onto the stack. To return to the previous view, you pop the current view from the stack.

Image

Figure 9-2 The Notes App uses a navigation bar.

Try This: Building a Three-View Application Using a Navigation Bar

It is easiest to learn the UINavigationController by example. In this task, you create a simple application containing three views. You navigate between the three views using a navigation bar. The first view has a button on the navigation bar’s right, which says “Next.” When you click the button, the application takes you to the next view. This view has a Back button and a button in the view rather than on the navigation bar. When you click the button in the view, the application takes you to a third view. The third view has a navigation bar and a title.

1. Create a new Window-based Application. Name the application ThreeViewNavCont.

2. Create three UIViewController classes, naming them FirstViewController, SecondViewController, and ThirdViewController. Be certain to also generate xib files for each class.

3. Open each of the xibs and add a label object to each with the text “View One”, “View Two”, and “View Three” so that you can easily tell which view is visible when running your app.

4. Save each xib file after changing it.

5. Open MainWindow.xib and drag a navigation controller from the library to the Document window (Figure 9-3). Notice Interface Builder shows the navigation controller’s canvas with a navigation bar and a view.

6. Select the navigation controller’s view controller. You can do this by expanding the column of icons representing the objects in the xib, then clicking the disclosure arrow next to navigation controller, and then selecting the view controller. Change the controller’s class to FirstViewController in the Inspector. Also change its NIB name to FirstViewController in the Inspector (Figure 9-4).

Image

Figure 9-3 Adding a navigation controller to MainWindow.xib

7. Save your changes.

8. Open ThreeViewNavContAppDelegate.h in Xcode. Add a UINavigationControllerIBOutlet declaration to the header file (Listing 9-1).

Listing 9-1 ThreeViewNavContAppDelegate.h

#import<UIKit/UIKit.h>
@interface ThreeViewNavContAppDelegate :
NSObject<UIApplicationDelegate> {
    UIWindow *window;
    UINavigationController *navController;
}
@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet UINavigationController *
navController;
@end

Image

Figure 9-4 Changing the view controller to FirstViewController

9. Add the UINavigationController to ThreeViewNavContAppDelegate.m and add the UINavigationController’s view to the window (Listing 9-2). Save and build.

Listing 9-2 ThreeViewNavContAppDelegate.m

#import "ThreeViewNavContAppDelegate.h"
@implementation ThreeViewNavContAppDelegate
@synthesize window;
@synthesize navController;
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [window addSubview: navController.view];
    [window makeKeyAndVisible];
    return YES;
}

- (void)applicationWillTerminate:(UIApplication *)application {
// Save data if appropriate.
}
- (void)dealloc {
    [navController release];
    [window release];
    [super dealloc];
}
@end

10. Switch back to MainWindow.xib in Interface Builder. Right-click ThreeViewNavContApp Delegate in the document window and connect the navController outlet to the UINavigationController (Figure 9-5).

11. Save your changes and click Run to run the application, and FirstViewController’s view should appear (Figure 9-6). The first step to using a navigation bar is to add a navigation controller to a document window. Upon adding the navigation controller, Interface Builder also adds a root view controller, and you changed this view controller to your view controller. Making this connection in Interface Builder allows the nib to manage the property’s life cycle. When you build and run the application, the application knows MainWindow.xib is the application’s main nib and loads it. Upon loading, the nib initializes the objects it manages, which includes the navigation controller property, navController. The navigation controller loads its root view controller. Because the root view controller has an associated navigation item, the navigation controller adds a navigation bar above the view with the navigation item’s title. Because MainWindow.xib handles all the application’s initialization, all you do in the application:didFinish-LaunchingWithOptions method is add the view to the window. After adding the navigation controller, you must provide navigation controls so that a user can move from view to view. You can either add a button to the navigation bar itself or add a control to a view’s canvas. The next few steps do both.

Image

Figure 9-5 Connecting the navigation controller

Image

Figure 9-6 The application running in iPhone Simulator

12. Open MainWindow.xib and select the navigation item in the document window (Figure 9-7). Change the navigation item’s title to First View.

Image

Figure 9-7 Selecting the navigation item in the Document window

13. Drag a bar button item from the library to the navigation bar and Interface Builder will highlight a rectangle where you can drop the button (Figure 9-8). Rename the button Next.

14. Save your changes and then open FirstViewController.h and add a new action called moveToNextView (Listing 9-3). Import SecondViewController and add SecondViewController as a property.

Listing 9-3 FirstViewController.h

#import <UIKit/UIKit.h>
@class SecondViewController;
@interface FirstViewController : UIViewController {
 SecondViewController * second;
}
@property (nonatomic, retain) SecondViewController * second;
-(IBAction) moveToNextView: (id) sender;
 @end

Image

Figure 9-8 Adding a button to FirstViewController’s navigation bar

15. Open FirstViewController.m and implement moveToNextView, as in Listing 9-4.

Listing 9-4 FirstViewController.m

#import "FirstViewController.h"
#import "SecondViewController.h"
@implementation FirstViewController
@synthesize second;

-(IBAction) moveToNextView: (id) sender {
 self.second = [[[SecondViewController alloc]
    initWithNibName:@"SecondViewController" bundle:nil] autorelease];
 [self.navigationController pushViewController:self.second animated: YES];
}

-(void)dealloc {
 [second release];
 [super dealloc];
}
@end

16. Save your changes.

17. Open MainWindow.xib in Interface Builder, select the FirstViewController, and connect its moveToNextView action to the Next button (Figure 9-9).

18. Save and click Run to run the application. Tapping the Next button results in the second view being displayed (Figure 9-10). Tap First View, and the application returns to the first view.

Image

Figure 9-9 Connecting moveToNextView action to the navigation button

Image

Figure 9-10 The application running in iPhone Simulator

In Step 13, you changed the default title to your view’s title. Actually, to be specific, you changed the default title to your view controller’s navigation item’s title. In Step 14, you added a bar button item to the navigation bar and set it as the navigation bar item’s rightBarButtonItem. Establishing this connection ensures the application displays the button on the bar’s right. You then created an action that, when clicked, pushes the second view controller onto the navigation controller’s stack. The navigation controller displays this view and a navigation bar containing the new view’s navigation bar element. Notice you must push view controllers onto the stack manually through code, as in Listing 9-4.

[self.navigationController pushViewController:self.second animated: YES];

If a view controller is in a navigation controller’s stack, then the navigationController property automatically refers to the navigation controller managing the stack. So, the navigation controller in ThreeViewNavContAppDelegate pushes FirstViewController’s SecondViewController onto the stack. Note that setting the animated parameter to YES causes the new view to slide in from the right or the old view from the left when navigating back.

As the task illustrates, creating an application using a navigation controller and associated navigation bar is not difficult. The Back button, and popping a view controller from the navigation controller, is implemented for you. You provide the control and action to push view controllers onto the navigation controller’s stack.

Adding Another View

You are not limited to bar buttons if you wish to push views onto a navigation controller’s stack. In the following steps, you first add a bar button item to SecondViewController. You then add an additional button to SecondViewController’s view, but instead of it being a bar button, you use a regular button.

1. Open the ThreeViewNavCont project in Xcode.

2. Open SecondViewController and add an IBOutlet for a UIBarButtonItem to SecondViewController as a property. Name the property navBut; don’t forget to synthesize the property in SecondViewController.m.

3. Open SecondViewController.m and implement the viewDidLoad method to set the navigationItem’s right bar button item to navBut:

self.navigationItem.rightBarButtonItem = navBut;

4. Note that every UIViewController has a navigationItem and that it is a read-only property.

5. Open SecondViewController.xib in Interface Builder and add a new bar button item to the document window. Connect the newly added bar button item to the navBut outlet (Figure 9-11). Name the new bar button item Next.

6. Save and run the application, and the second view now displays its title in the navigation bar (Figure 9-12). But notice, clicking the Next button in the navigation bar has no effect because you haven’t connected it to a method yet.

7. Open SecondViewController.h and add a new action called moveToNextView. Import ThirdViewController. Add a ThirdViewController as a property (Listing 9-5).

Listing 9-5 SecondViewController.h

#import <UIKit/UIKit.h>
@class ThirdViewController;
@interface SecondViewController : UIViewController {

Image

Figure 9-11 Adding a UIBarButtonItem

Image

Figure 9-12 The application displaying the second view controller’s navigation item’s title

 ThirdViewController * third;
 UIBarButtonItem * navBut;
}
@property (nonatomic, retain) IBOutlet UIBarButtonItem * navBut;
@property (nonatomic, retain) ThirdViewController * third;
-(IBAction) moveToNextView: (id) sender;
@end

8. Open SecondViewController.m and implement moveToNextView, as in Listing 9-6. Save and build.

Listing 9-6 SecondViewController.m

#import "SecondViewController.h"
#import "ThirdViewController.h"
@implementation SecondViewController
@synthesize third;
@synthesize navBut;
-(void) viewDidLoad {
 self.navigationItem.title =
    @"SecondView"; self.navigationItem.rightBarButtonItem = navBut;
}

-(IBAction) moveToNextView: (id) sender {
 self.third = [[[ThirdViewController alloc]
    initWithNibName:@"ThirdViewController" bundle:nil] autorelease];
 [self.navigationController pushViewController: self.third animated: YES];
}

-(void)dealloc { [third release]; [super dealloc];
}
@end

9. Click SecondViewController.xib to edit it with Interface Builder. Connect the bar button’s selector to the File’s Owner moveToNextView action (Figure 9-13).

10. Save and run the application. The second view now has a Next button and tapping it moves to the next view (Figure 9-14). Now consider pushing a view onto the stack using a regular button.

11. Open SecondViewController.xib and add a button to the view. Connect the button to moveToNextView (Figure 9-15). Connect to the button’s Touch Up Inside action.

12. Save and run the application. Click the button on the second view, and it, too, navigates to the third view.

Image

Figure 9-13 Connecting the bar button to the moveToNextView action

Image

Figure 9-14 The third view, after clicking the Next button on the second view

Image

Figure 9-15 Connecting a button to the moveToNextView method

Using a button rather than a bar button item is that easy. Typically, though, in most iOS applications, you will see a table in the view rather than a button (see Figure 9-1). For instance, SecondViewController might have an embedded table listing categories. Upon clicking a table row, you would invoke the moveToNextView method, passing the specific table row’s identifier as a parameter. The App Store application is an example of this type of navigation (see Figure 9-1).

Try This: See How a Utility Application Uses NavigationBar

Create a new Utility application using the Utility Application template, and then review the code. You will notice it uses a navigation bar in the FlipsideView to display a title and a Done button.

In our previous example, every view had a NavigationBar and we pushed each subsequent view onto a stack of views. With a Utility application, the show info button creates a new modal view and only that flipside view has a NavigationBar. Instead of defaulting to popping the view from the stack, the Done button invokes a done method that dismisses the modal view.

Remember that all of the application templates in Xcode are just generating code and xib files for you and you can experiment with creating any of them and then looking through the generated code to better understand how iOS applications work.

More on the UINavigationController

You are not limited to pushing items onto a stack. You can also pop items off the stack. You can also modify the navigation bar, hiding elements, adding new ones, and making other modifications.

Popping View Controllers

You pop view controllers from a stack using the method popViewControllerAnimated:. This method pops the top view controller off the navigation controller’s stack and updates the displayed view to the stack’s next view controller’s view.

(UIViewController *) popViewControllerAnimated: (BOOL) animated

The method takes one parameter, which indicates if the transition should be animated. The method also returns the popped view controller, should you wish to retain it for future use.

Other methods you might use include popToRootViewControllerAnimated: and popToViewController:animated:. Refer to Apple’s online reference, “UINavigationController Class Reference,” for more information.

Configuring the Navigation Bar

You can also hide the navigation bar by calling the navigation controller’s setNavigationBarHidden: method.

-(void)setNavigationBarHidden:(BOOL)hidden animated:(BOOL)animated

This method hides or displays the navigation bar, depending upon if you passed YES or NO as the initial parameter. You also specify if the navigation bar should slide in from the top by specifying YES for the animated parameter.

You might also change a navigation bar’s style by changing its style property. You can use code to change the navigation bar’s style, but the easiest way to do this is through Interface Builder. You can also change a navigation bar’s color. You change the color using the tintColor property.

Try This: Using a Navigation Controller in a Tab

Applications usually use a navigation bar with other navigation views, such as a tab bar or table view. You haven’t learned about table views yet—you won’t learn about using a table view with a navigation bar until Chapter 10. However, you learned about the tab bar in Chapter 8. A navigation bar might be placed within a tab bar. For instance, returning to the App Store application, notice the navigation screens are steps within the Categories tab (see Figure 9-1). The Featured, Categories, Top 25, and Updates tabs are different views on the same data. The Search tab is a subtask. Within the Categories tab, there is a navigation bar combined with a table view. This combination provides a way to drill down hierarchically to a specific application.

Although you don’t learn about tables until Chapter 10, consider a navigation bar in a tab.

1. Create a new Window-based Application. Name the application NavInTab.

2. Create two new UIViewController classes. Name the first FirstTabViewController and the second StepTwoViewController; be certain to create nibs for both.

3. Open both newly created nibs and change the background color for each view.

4. Open MainWindow.xib and add a UITabBarController to the document.

5. Delete the first tab bar view controller. Drag a navigation controller to the document and drop it so that it is the first item below the tab bar. Change the navigation controller’s root view controller to FirstTabViewController by changing its class and nib name in the Inspector. The canvas should indicate the view is from FirstTabViewController.nib (Figure 9-16).

Image

Figure 9-16 Canvas indicates view is from a different nib.

Image

Figure 9-17 Bar button added to document window

6. Change the navigation item’s title from “Root View Controller” to “step one.”

7. Drag a bar button item from the library to the navigation bar in the editing window and drop it in the area for a right-hand button (Figure 9-17). Change the button’s title to Next.

8. Save your changes.

9. Open NavInTabAppDelegate.h and NavInTabAppDelate.m and adopt the UITabBarController Delegate protocol. Also add a UITabBarController property and a UINavigationController property. Modify applicationDidFinishLaunching so that it loads the tabBarController property’s root view. The files should match Listings 9-7 and 9-8. Save and build.

Listing 9-7 NavInTabAppDelegate.h

#import<UIKit/UIKit.h>
@interface NavInTabAppDelegate : NSObject<UIApplicationDelegate,
      UITabBarControllerDelegate> {
 UIWindow *window;
 UITabBarController *tabBarController;
 UINavigationController *navBarController;
}

@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet
      UITabBarController*tabBarController;
@property (nonatomic, retain) IBOutlet
      UINavigationController *navBarController;
@end

Listing 9-8 NavInTabAppDelegate.m

#import "NavInTabAppDelegate.h"
@implementation NavInTabAppDelegate
@synthesize window;
@synthesize tabBarController;
@synthesize navBarController;

- (BOOL)application:(UIApplication *)application
      didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  [window addSubview:tabBarController.view];
  [window makeKeyAndVisible];
  return YES;
}

-(void)dealloc {
  [tabBarController release];
  [navBarController release];
  [window release];
  [super dealloc];
}
@end

10. Open MainWindow.xib in Interface Builder and connect the NavInTabAppDelegate’s navBarController to the newly added navigation controller (Figure 9-18). Connect the tabBarController to the newly added tab bar controller.

11. Save your changes.

12. Edit StepTwoViewController.m and implement the viewDidLoad method so that it sets the navigationItem’s title to “step two” (Listing 9-9).

Listing 9-9 StepTwoViewController’s viewDidLoad method

-(void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.title = @"step two";
}

13. Open FirstTabViewController.h and import StepTwoViewController.h and NavInTabAppDelegate.h. Also add the method signature, takeNextStep (Listing 9-10).

Image

Figure 9-18 Connecting the navBarController

Listing 9-10 FirstTabViewController.h

#import<UIKit/UIKit.h>
#import "StepTwoViewController.h"
#import "NavInTabAppDelegate.h"
@interface FirstTabViewController : UIViewController {
}
-(IBAction) takeNextStep: (id) sender;
@end

14. Open FirstTabViewController.m and implement the newly added action. The file should match Listing 9-11. Note that you’ll also want to call dealloc for third view when the second view is deallocated. Popping a view from the stack doesn’t automatically deallocate it.

Listing 9-11 takeNextStep method added to FirstTabViewController.m

-(IBAction) takeNextStep : (id) sender {
 StepTwoViewController *varSecondViewController =
     [[StepTwoViewController alloc] initWithNibName:
     @"StepTwoViewController" bundle:nil];
 [self.navigationController pushViewController:varSecondViewController
     animated: YES];
}

15. Open MainWindow.xib and connect the bar button item to the FirstViewController’s takeNextStep method.

16. Save and run the application in the iPhone Simulator. You should have a two-tab application, where the first tab has an embedded navigation control (Figure 9-19).

Image

Figure 9-19 The finished application in iPhone Simulator

Summary

Creating an application with a navigation bar is straightforward. In the application’s MainWindow.xib, add a UINavigationController. Set the navigation controller’s root view controller, and create one or more other view controllers. Then add code that pushes the view controllers onto the navigation controller’s stack. When a view controller is pushed onto the stack, it becomes the topmost view controller, and so the application displays the view controller’s view. Popping a view controller off the stack is provided by default if you do not make the navigation bar’s Back button invisible. If you do make the Back button invisible, or somehow disable the button, you must use one of the navigation controller’s methods for popping view controllers.

In this chapter, you learned how to create an application containing a navigation controller with three views. You then looked at how the Utility Application template uses NavigationBar in a different manner. Finally, you embedded a navigation controller within a tab in a tab bar. But this chapter did omit the most common navigation controller use: a table combined with a navigation controller. In the next chapter, after learning about tables, we’ll correct this omission by presenting a navigation controller combined with a table controller. After learning about this combination, you will have enough knowledge of view controllers that you should be able to tackle most iOS application navigation strategies.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset