Start up XCode, choose "File/New Project" from the menu, select "Window-Based Application" and name it "WinNav". After XCode has done it's magic, we have the following project structure.
WinNav
Classes
WinNavAppDelegate.[hm]
Resources
MainWindow.xib
Info.plist
When we're using Interface Builder (IB) to create objects for us, we should usually start by defining Objective C pointers in the source code and then use IB to "connect" the objects to the pointers. When the application is launched, the IB file loading procedure will actually assign values to the pointers.
Classes/WinNavAppDelegate.h
As was stated initially, we're going use a navigation controller to navigate between three custom view controllers. Furthermore, we're going to add "next"-buttons on the two first view controllers which will take us to the next view controller. Therefore, we start by declaring a navigation controller, three view controllers and two buttons - pretty logical, huh? How do we do this? Simple, open WinNavAppDelegate.h in XCode and add the following lines after the "UIWindow *window" line that came with the template:
// DON'T ADD THE FOLLOWING LINE - JUST USED FOR REFERENCE!!!
UIWindow *window;
// navigation controller
UINavigationController *navigationController;
// view controllers
UIViewController *viewController;
UIViewController *viewController2;
UIViewController *viewController3;
// buttons
UIButton *button;
UIButton *button2;
Since we're going to manipulate all these objects from IB, we have to declare them as properties (to make them accessible to external classes) as well as declare them as IBOutlets so that IB will detect them, when it scans our class defintion files. We do this by adding the following block of code after the 'window' property that came with the template.
// DON'T ADD THE FOLLOWING LINE - JUST USED FOR REFERENCE!!!
@property (nonatomic, retain) IBOutlet UIWindow *window;
// navigation controller
@property (nonatomic, retain) IBOutlet UINavigationController *navigationController;
// view controllers
@property (nonatomic, retain) IBOutlet UIViewController *viewController;
@property (nonatomic, retain) IBOutlet UIViewController *viewController2;
@property (nonatomic, retain) IBOutlet UIViewController *viewController3;
// buttons
@property (nonatomic, retain) IBOutlet UIButton *button;
@property (nonatomic, retain) IBOutlet UIButton *button2;
- (IBAction)next;
- (IBAction)next2;
If you've read the previous posts all this should be pretty straight forward to you, but you might have forgotten what the strange IBAction stuff is all about. An action is a way to associate an UI-event (touching a button for example) with an action (a method in a class).
Classes/WinNavAppDelegate.m
We declared a bunch of properties in the h-file, so the first thing we should do is to add matching @synthesize-instructions to actually create the code required to implement the property specifications.
// DON'T ADD THE FOLLOWING LINE - JUST USED FOR REFERENCE!!!
@synthesize window;
// navigation controller
@synthesize navigationController;
// view controllers
@synthesize viewController;
@synthesize viewController2;
@synthesize viewController3;
// buttons
@synthesize button;
@synthesize button2;
Ok, now that the properties are implemented, we should implement the action methods we declared using the IBAction statements in the h-file. Add the following lines to the end of the m-file, just above the @end-statement.
- (IBAction)next {
[navigationController pushViewController:viewController2 animated:YES];
}
- (IBAction)next2 {
[navigationController pushViewController:viewController3 animated:YES];
}
The 'next' method will be associate with the "next"-button on the first view controller and the "next2"-button will be associated with the "next"-button on the second view controller. Both these methods do the same thing, they "push" a view controller onto the navigation controller, which automatically (thanks to the navigation controller) will take us to the new view (the one we push). The button on the first view takes us to the second view and the button on the second view takes us to the third. Moving "backwards" is automatically handled by the navigation controller thanks to an automatically added "back"-button in the top left corner.
To make all the stuff we have declared visible once we start the application, we need to add the navigation controller's view to our window. We do this by adding a 'addSubView' method call in the 'applicationDidFinishLaunching' that came with the template:
// navigation controller
[window addSubview:[navigationController view]];
// DON'T ADD THE FOLLOWING LINE - JUST USED FOR REFERENCE!!!
[window makeKeyAndVisible];
Resources/MainWindow.xib
Now that we've prepared our source code for what we want to do, it's time to make an IB file which creates all the objects for us, so double-click on Resources/MainWindow.xib to load the file into IB. Switch to hierarchical view mode in the MainWindow.xib window in IB, by pressing the middle icon just above the "View mode" text in the upper left corner of the window. This should present the contents of the file as:
File's Owner [UIApplication]
First Responder [UIResponder]
Win Nav App Delegate [WinNavAppDelegate]
Window [UIWindow]
To really see if we understand how to use IB, we'll start by deleting the last two objects by selecting them and press backspace.
Win Nav App Delegate
So how do we re-create the "Win Nav App Delegate" object? Choose Tools/Library from the IB menu or press CMD-L. Select "Cocoa Touch Plugin" from the Library window and then "Controllers". Scroll down to the Object-icon and drag it into the MainWindow.xib window. It should be automatically selected so press CMD-4 to bring up the Identity tab of the Inspector window. Change the class to WinNavAppDelegate (our class) and you should see how the list of outlets get populated in the "Class outlets" section; all our buttons and view controllers as well as the window and navigation controller should be present. You should also see our two actions 'next' and 'next2' in the "Class actions" section.
Connect the "Win Nav App Delegate" to the 'delegate' property of "File's Owner" by selecting "File's owner" and CTRL-dragging from it to "Win Nav App Delegate". A blue line should appear and when you release the mouse button a window called "Outlets" should appear. Select 'delegate' from it. CTRL-click "Win Nav App Delegate" and then "File's Owner" to verify that the 'delegate' outlet is correctly connected.
Window
Let's re-create the "Window" object, by going to the "Windows, Views & Bars" branch in the Library window. Drag the Window icon into the MainWindow.xib window. Connect the Window to the 'window' property of "Win Nav App Delegate" by selecting "Win Nav App Delegate" and CTRL-dragging from it to "Window".
Navigation Controller
What's next? Well, we need a navigation controller so select the "Controllers" branch in the Library window again. Drag the "Navigation Controller" into the MainWindow.xib window. See the small arrow to the left of the newly added object? Press it to expand the hierarchy under the controller and you should see a "Navigation Bar" object and a "View Controller (Navigation Item)" object. Yep, there's another small arrow to the left of this object, so press that as well. Look, a "Navigation Item (Navigation Item)" object appeared. IB apparently did a lot of work for us when we drag and dropped the "Navigation Controller" icon. Even if this is a "from scratch" tutorial we're going to accept this help since we'll be adding two more view controllers by ourselves soon. Connect this to the 'navigationController' outlet of "Win Nav App Delegate" by CTRL-dragging from "Win Nav App Delegate" to "Navigation Controller" and select the 'navigationController' outlet.
Navigation Bar
Automatically created when we dragged the "Navigation Controller" icon from the Library Window. This is used "internally" by the "Navigation Controller" and shouldn't be manipulated.
View Controller (Navigation Item)
Automatically created when we added the "Navigation Controller from the Library. It's a simple UIViewController, but CTRL-click it to see that it's 'navigationItem' property is connected to the "Navigation Item (Navigation Item)" object. This object was placed "under" the "Navigation Bar" object thanks to some special handling in IB - navigation controllers are prepared for it.
Navigation Item (Navigation Item)
Also automatically created by IB. This object was placed "under" the "View Controller" also thanks to some special handling in IB. It is used to display the title and navigation buttons of the "View Controller". Double-click it to bring the "edit window" for it to the front. Double-click the text "Navigation Item" at the top and change it to "First". Notice how the text "(First)" replaced ("Navigation Item)" in the MainWindow.xib window, both for the "Navigation Item" and the "View Controller".
A first test run
Let's take a brief pause and save our IB file (CMD-S), return to XCode to build and run (CMD-Return) and wait for the iPhone simulator to start. You should see a white background with a blue bar at the top saying "First". That's the title of the view controller that was automatically added by IB.
View Controller (Second)
To create this object, bring up the Library window in IB (CMD-L) and drag a "View Controller" icon from the "Controllers" section to the end of the list of objects in the MainWindow.xib window and drop it there. We should create a similar hierarchy as for the automatically created view controller so drag the "Navigation Item" icon from the "Windows, Views & Bars" secion in the Library and drop it onto the newly added view controller. It should "swallow" it so that it appears "under" it instead of just "below" it. Double-click the newly added navigation item to bring up the edit window for it and then double-click the "Title" text and change it to "Second".
Connect the newly created view controller object, by CTRL-dragging from the "Win Nav App Delegate" object to the "View Controller (Second)" object and choose the 'viewController2' outlet from the menu that pops up.
View Controller (Third)
Repeat the steps from above, but name it "Third" instead. Easy, huh?
Adding views
View controllers without views are pretty boring, so we'll add a view to each of our controllers. There are two ways of doing this. Either you drag the "View" icon from the "Windows, Views & Bars" section of the Library onto the appropriate "View Controller" object in the MainWindow.xib window or you double-click the appropriate "View Controller" object in the MainWindow.xib window to bring up the edit window and then drag the "View" icon into the edit window (the big area that says "View). Go ahead and try both alternatives.
Adding buttons
The navigation controller automatically provides a means for moving "backwards" among its view controllers, just like a "Back" button in a web browser, but it does not provide a "Forward button". Therefore, we have to provide our own. We need one button on the first view controller so we can get to the second and one on the second so we can get to the third.
Double-click on the first view controller (the one IB automatically added for us under the navigation controller) to bring up its edit window. As an alternative, you could also double-click on the view controllers view that we added above. Now, drag the "Round Rect Button" icon from the "Inputs & Values" section of the Library window (CMD-L) and drop the icon anywhere in the view controllers edit window that we just brought up. Don't drop it on the blue navigation bar at the top, though. Double-click the newly added button and name it "Second".
Connect the newly created button by CTRL-dragging from "Win Nav App Delegate" to the button and select the 'button' outlet from the menu that pops up.
Repeat the steps for the second view controller but name the button "Third" and connect it to the 'button2' outlet instead.
Time for a test run again
Save the IB-file (CMD-S) and go to XCode to build and run (CMD-R). You should see a white screen with the title "First" in the blue navigation bar at the top and a button titled "Second". That's pretty cool, but hey nothing happens when we press the button! What kind of tutorial is this?
Bringing the buttons to life
Expand the hierarchies for the first and second "View" objects in the MainWindow.xib window by pressing the small arrow that appeared to the left of them when we added the buttons to them. You should see that a "Rounded Rect Button (Second)" and "Rounded Rect Button (Third)" have been added to the object hierarchy.
Select the first button in the MainWindow.xib window in IB and CTRL-drag to "Win Nav App Delegate" button. A small window named "Events" should pop up displaying the two IBActions 'next' and 'next2' we defined in Classes/WinNavAppDelegate.h. Choose 'next'.
Repeat the steps for the second button, but choose 'next2' from the list of events instead.
Time for another test run!
Save the IB-file (CMD-S) and go to XCode to build and run (CMD-R). Try to press the "Second"-button to see what happens! Whoa! That's amazing! Look at those smooth movements! Now try pressing the "Third"-button and see how we switch to the third view controller - pretty amazing, right? But that's not all, try pressing the "Second"-button in the upper left corner of the screen - inside the navigation bar. Yeah, that's a "Back"-button which takes us to the previous view controller. So now you can navigate freely between the three view controllers. Not bad, huh? ;)