Implementing a navigation controller (UINavigationController) with Interface Builder

During the different SDK releases, Apple has changed many things. Now, developers can build their own applications using different approaches, but I personally believe that an intensive use of Interface Builder is a good strategy to set up in few minutes a project and easily maintain it.

During the training classes, I collected the request of my students and most of the time, they wish to use more and more Interface Builder, because it is more intuitive and easier to use than simply typing code.

In this post, I want to explain how to build the infrastructure for the UINavigationController using Interface Builder. I think this is the best, cleanest and quickest way to build an app. If you just repeat this exercise a couple of times to understand the concept, you will be able to build a navigation controller-based app in few minutes.

To better understand what we do, I will start from a window-based project without taking advantage of the view-based template prepared by Apple. So, open Xcode and create a new project. Select a Window-based Application template and name it MyNav. We could have chosen the View-based Application template and Xcode would have setup the whole infrastructure for us, but then you loose all the magic behind it. So, I prefer you build it from the scratch, so that you will learn how it works and you can easily modify it to create more complex functionalities.

Give a look at the created project. It contains three files: MyNavAppDelegate.h, MyNavAppDelegate.m and MainWindow.xib. We need to modify these three files to go on, but let us start with some design.

Suppose you want to navigate 3 views: view1, view2 and view3. The view1 is the view appearing as soon as the app finishes launching. This is called the main view. Since it is the first view in the sequence, view1 is also called the root view. Root view and main View do not always coincide. For example, in the Contacts app, the main view is the All Contacts list, while the Root View is the Groups view.

Each view of our project will be a UIViewController and the navigation controller will be responsible to push or pop the next or the previous view onto the screen as they were in a stack. So, let us start.

Modify the MyNavAppDelegate.h file, so that it looks as follows:

Now, let us modify the implementation file. Edit the MyNavAppDelegate.m file like this:

Now, fire up Interface Builder, double-clicking the MainWindow.xib file. From the Library drag a Navigation Controller and drop it in the MainWindow.xib.

Control-click the My Nav App Delegate object in the MainWindow.xib window and, when the HUD window opens, connect the myNavController outlet with the recently added Navigation Controller.

So, what have we done in the last part? It is very simple: we declared in the @interface of the MyNavAppDelegate a UINavigationController outlet. In the @implementation, we should have allocated and initialized this UINavigationController, but to avoid this, we added a Navigation Controller object with Interface Builder to our project. In this way, the XIB file contains the Navigation Controller. When we launch the app, the MainWindow.xib file, containing the Navigation Controller, is automatically loaded. Since this is a generic object to let Xcode understand that we are referring to the same Navigation Controller defined in the @interface, we need to connect the outlet of the App Delegate to the UINavigationController.

Now, we need to add the 3 UIViewController(s) to manage each view in the stack. The use of the UIViewController instead of simple UIView is requested by the fact that a UIViewController is a controller and thus, it is able to manage complex functionalities, such as screen rotations, that maybe you will use later.

The approach to setup a UIViewController and its XIB file is the same for each view, so I show you how to do it only for one of them. Then, you simply repeat the following steps:

  • Right-click the Classes group in the project window of Xcode and select Add->New File…
  • Select the UIViewController subclass template from the Cocoa Touch Classes and click Next.
  • Name the view FirstViewController (make sure that the Also Created flag is selected) and click Finish. You get two files (FirstViewController.h and FirstViewController.m).
  • Right-click again the Classes group and choose Add -> New File… This time, select View XIB template from the User Interface under iPhone.
  • Click Next and name the file FirstViewController.xib.
  • Click Finish.

Repeat the last paragraph for the second and third view (name them SeconViewController and ThirdViewController).

When you have the three controllers, double click the FirstViewController.xib. The MainWindow.xib window contains 3 objects: File’s Owner, First Responder and View. The File’s Owner is a Proxy Object: it simply represents in IB an object that you have created somewhere else (coding or using IB). We need to specify which object is exactly. To do this, select the File’s Owner and the Identity pane in the Interface Builder Inspector (Tools -> Identity Inspector). Choose as Class name FirstViewController. Repeat this step for the SecondViewController and for the ThirdViewController. When done, you have clearly associated each class to its XIB file.

Now, our File’s Owner represents the FirstViewController object. Right-click it and connect the view outlet with the View object. Open the View object (double-click it) and select the Attributes pane in the Inspector (Tools -> Attributes Inspector). Click on the Background color picker and change the color to red, so that we can distinguish it from the other views we are going to set up.

Now, we have to tell the Navigation Controller that the FirstViewController is the first view we want to load (the Main View, remember?) and use it as root view. Here, there is a small trick. Open again the MainWindow.xib file and double click the Navigation Controller. Click in the window of the Navigation Controller and select the Identity Inspector.

Select as class name FirstViewController. Then, select the Attributes Pane and select FirstViewController as NIB Name. The Navigation Controller should show now a link to the FirstViewController.xib as shown here on the right-hand side. Before you can Build and Run, choose the Detailed View of the MainWindow.xib. Click on the triangle close to the UINavigationController. Inside it, there is UIViewController. You need to make sure that this is is the right one. Select it and set its class name to FirstViewController in the Identity Inspector. In the same way, set to FirstViewController, the XIB Name to FirstViewController in the Attributes Inspector. If you miss these steps, your app will not work. It should look like in the following picture.

You can now Build and Run. You will get a window with a NavigationBar and red view. Let’s go back to the project.

So, we have set our root view. Now, we have to inform each view about the next view of the desired view sequence. You will see that many functionalities are for free and the code we are going to write is represented by few lines.
Edit the FirstViewController.h so that it looks like this:

Remember to synthesize the property and add the following header #import “SecondViewController.h” in the FirstViewController.m file.

Now, open the FirstViewController.xib and add a UIViewController to the MainWindow.xib FirstViewController.xib window. Select this view controller and set its class name to SecondViewController in the Identity Inspector. Then, set also to SecondViewController the XIB Name in the Attributes Inspector. Now, finally, connect the File’s Owner outlet mySecondViewController to the view controller.

We do the same for the second view controller. Before that, open the SecondViewController.xib file and add a UIViewController object to the MainWindow.xib SecondViewController.xib window. Select this view controller and set its class to the ThirdViewController in the Identity Inspector and set its XIB Name to ThirdViewController in the Attributes Inspector.
Now, open the SecondViewController.h file and modify it as follows:

Remember to synthesize the property and add the following header #import “ThirdViewController.h” in the SecondViewController.m file.

Now, build and run it. You don’t see any difference with the previous run. The infrastructure is already set up, but we need to add some way to push the next view to the screen. We can do it in different way. We choose the simplest one, using a push button in the center of the current view.

Add a button to the first and second view controllers. For each of them, add the following action in the header file of the corresponding class:

In the implementation, add the following:

Repeat the previous code for the second view controller. Don’t forget to connect the button to the IBAction of the File’s Owner. I attach the project I only add small things to make it to like nicer. If you have any question, simply contact me.

Have a nice coding!!!




(Visited 52 times, 1 visits today)