iPhone Programming Fundamentals: Understanding View Controllers

ne of the first things you will learn about when you begin programming iPhone projects is view controllers. Beginners often get intimidated by the amount of work they need to get a simple application going. However, you do much of the UI management in iPhone programming with view controllers; therefore, understanding what they do and how they work is critical to successful iPhone programming. This article explains the concepts and use of view controllers in iPhone programming. By the end of this article you should have a solid understanding of view controllers and be on your way to creating some great applications.

Getting Started

As usual, building a real project is the best way to get started and see how things fall into place along the way. To begin, start Xcode and create a new View-based Application project named VCExample (see Figure 1).

 
Figure 1. New Project: Select the View-based Application item from the New Project screen in Xcode.

Understanding the Basics

The new project includes several project templates that Xcode creates for you. These usually contains sufficient underlying code to make everything work, so it’s worth while spending a bit of time examining the code.

 
Figure 2. Default Files: The figure shows the files that Xcode creates by default for a new view-based application.
Author’s Note: If you’re completely new to building iPhone applications, you might want to read my previous article “Inside the iPhone: Getting Started” and the brief sidebar “Objective-C File Types” before continuing with this article.”

First, observe that there are four source code files in the project (see Figure 2). The first two, VCExampleApDelegate.h and VCExampleApDelegate.m, manage application loading and unloading. The next two, VCExampleViewController.h and VCExampleViewController.m, define the view controller class that manages loading and unloading a view (think of a view as a screen in iPhone, or if you are a .NET programmer, think of a view as a Windows Form). In addition, there are also two NIB files: VCExampleViewController.xib and MainWindow.xib. MainWindow.xib contains the main window in which your application will load. It essentially loads the view contained in the VCExampleViewController.xib file.

Here’s the content of the VCExampleAppDelegate.h file:

#import @class VCExampleViewController;@interface VCExampleAppDelegate :    NSObject  {    UIWindow *window;    VCExampleViewController *viewController;}@property (nonatomic, retain) IBOutlet UIWindow *window;@property (nonatomic, retain) IBOutlet    VCExampleViewController *viewController;@end

This file defines a view controller object called VCExampleViewController. When the application has finished initializing, it fires the applicationDidFinishLaunching: event handled in the VCExampleAppDelegate.m file, which loads the view represented by this view controller:

#import "VCExampleAppDelegate.h"#import "VCExampleViewController.h"@implementation [email protected] window;@synthesize viewController;- (void)applicationDidFinishLaunching:(UIApplication *)application {            // Override point for customization after app launch        [window addSubview:viewController.view];    [window makeKeyAndVisible];}- (void)dealloc {    [viewController release];    [window release];    [super dealloc];}@end

 
Figure 3. MainWindow.xib: The figure shows the contents of the MainWindow.xib file in list mode.

Double-click on MainWindow.xib to edit it in Interface Builder. Observe the MainWindow.xib window (see Figure 3; I have shown it in list mode).

Specifically, it contains a view controller of type VCExampleViewController—an instance of the VCExampleViewController class. You can verify this by selecting the view controller instance and viewing its Identity Inspector window (see Figure 4).

 
Figure 4. Confirming Identity: Here’s the VCExampleViewController instance viewed in the Identity Inspector.

To continue the default file exploration, Listing 1 shows the code in the VCExampleViewController.m file.

The code in Listing 1 defines various methods for you, and includes a few commented-out methods as well. All the methods are event handlers for various events fired by the view controller. For example, the controller fires the viewDidLoad method after it loads the view into memory. To create the UI for your view programmatically, you can override the loadView method.

Now, double-click on the VCExampleViewController.xib file and examine its contents (see Figure 5). Notice that the File’s Owner item is mapped to the VCExampleViewController class.

 
Figure 5. VCExampleViewController.xib: Here’s what you’ll see when you open the VCExampleViewController.xib file.

 
Figure 6. New View: In this figure, the view’s background color has been changed to a green color, and a Button added.

Double-click on the View item, set its background color to green, and add a Button view to it (see Figure 6). Save the project in Interface Builder before you continue.

 
Figure 7. Handling Events: To connect the Button view with the action, drag it to the File’s Owner item and select displayView:.

Back in Xcode, open the VCExampleViewController.h file and add the following code in bold (remember to save the file after adding the code):

#import @interface VCExampleViewController : UIViewController {}//---declare an action for the Button view----(IBAction) displayView:(id) sender;@end

Back in Interface Builder, control-click and drag the Button view to the File’s Owner item and select displayView: (see Figure 7).

This will connect the “Touch Up Inside” event of the Button view with the displayView: action that you have just added.

 
Figure 8. The Application in Action: Pressing the button now displays an alert, proving that the event handler fired properly.

Now, you need to add some code to the VCExampleViewController.m file, so that when a user clicks the Button view, you can perform some simple action to prove that the action was linked correctly to the event. Add the following code to the displayView: method:

-(IBAction) displayView:(id) sender{        UIAlertView *alert = [[UIAlertView alloc]           initWithTitle:@"Button Pressed"           message:@"You have pressed the Button view."          delegate:self           cancelButtonTitle:@"OK"           otherButtonTitles:nil];    [alert show];    [alert release];}

Save the project in Xcode, and then press Command-r to test the application on the iPhone Simulator. When you press the Button view, you will now see an alert display a message (see Figure 8).

Adding a New View Controller

You’ve seen how easy it is to get started using the View-based Application template. All you need to do is to add some views to the View window of an XIB file and voila, everything works. Now, here’s how to modify the application so that when a user presses the Button view, the application switches to another view that displays several other views. Showing different views depending on what the user selects is a very common action. You can use this example to gain a deeper understanding of how view controllers work.

Using the same project, add a new view controller class to the project. In Xcode, right-click on the Classes group and elect to add a new file. Choose the Cocoa Touch Classes group and then select the UIViewController subclass template (see Figure 9).

 
Figure 9. Cocoa Touch Classes: Select the UIViewController subclass to add a new view controller.

Name the view controller SecondViewController.m.

Next, add a new view XIB file so that you can create the UI with Interface Builder. Right-click on the Resources group in Xcode and add a new file. Choose the User Interfaces group and then select the View XIB template (see Figure 10). Name the file SecondView.xib.

 
Figure 10. Add a XIB File: From the User Interfaces group, select the View XIB file type to add a new View to your project.

 
Figure 11. New Files: The figure shows newly added files in the project.

 
Figure 12. Setting the Class: Set the File’s Owner item to the SecondViewController class.

Xcode should now display the files you just added (see Figure 11).

Double-click on the SecondView.xib file to edit it in Interface Builder. In the SecondView.xib window, select the File’s Owner item, and view its Identity Inspector window (see Figure 12). Set its Class to SecondViewController.

Connect the File’s Owner item to the View item by control-clicking it and then dragging it over the View item (see Figure 13).

 
Figure 13. Connect View: Connect the File’s Owner item to the View item.

 
Figure 14. Second View: Change the background color of the View to orange, and add a Button view.

Double-click on the View item and change its background color to orange, and then add a Button view (see Figure 14).

In Xcode, add the following line to the SecondViewController.h file:

#import @interface SecondViewController : UIViewController {}//---action for the Return button----(IBAction) btnReturn:(id) sender;@end

Back in Interface Builder, connect the Return button to the File’s Owner item, and select btnReturn:.

Switching the Views

So far, you’ve added a new view controller class and connected it to a XIB file. You need to modify it so that pressing the “Display SecondView” button in the first view causes the second view to load.

In the VCExampleViewController.m file, when a user clicks the button, the following bold code lines add the view represented by the second view controller to the current view, thereby making the second view appear:

#import "VCExampleViewController.h"//---import the header file for the view controller---#import "SecondViewController.h" @implementation VCExampleViewControllerSecondViewController *secondViewController;//---add the view of the second view controller to the current view----(IBAction) displayView:(id) sender{    secondViewController = [[SecondViewController alloc]                                     initWithNibName:@"SecondView"                                     bundle:nil];    [self.view addSubview:secondViewController.view];}- (void)dealloc {    //---release the memory used by the view controller---    [secondViewController release];    [super dealloc];} @end

In the SecondViewController.m file, code the btnReturn: action so that it removes the second view, making it disappear, and revealing the previous view:

#import "SecondViewController.h"@implementation SecondViewController-(IBAction) btnReturn:(id) sender {    [self.view removeFromSuperview];}

That’s it. Press Command-r to test the application. Now, clicking the “Display SecondView” button, displays the second view (see Figure 15).

 
Figure 15. Changing Views: The buttons now let you switch smoothly back and forth between the two views.

Similarly, when you press the Return button, the second view disappears.

Animating the Transitions

You’ve seen how to create a transition from one view to another using buttons. However, the transitioning happens very quickly, and isn’t particularly exciting, visually. To live up to iPhone users’ high expectations, you will need to add some animations to the transition. Fortunately, this is very easy using the APIs provided in the SDK.

In the VCExampleViewController.m file, add the following lines of code in bold:

-(IBAction) displayView:(id) sender{   secondViewController = [[SecondViewController alloc]                            initWithNibName:@"SecondView"                            bundle:nil];        [UIView beginAnimations:@"flipping view" context:nil];    [UIView setAnimationDuration:1];    [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];[UIView setAnimationTransition:UIViewAnimationTransitionCurlDown           forView:self.view cache:YES];        [self.view addSubview:secondViewController.view];    [UIView commitAnimations];}

Basically, the preceding code adds some animation during the transitioning process, setting the following parameters:

 
Figure 16. Smooth Animation: The transition between views is now a smooth page-turn animation.
  • Animation duration to one second
  • Animation curve to UIViewAnimationCurveEaseInOut (other available animation types are UIViewAnimationCurveEaseIn, UIViewAnimationCurveEaseOut, and UIViewAnimationCurveLinear)
  • Animation transition type to UIViewAnimationTransitionCurlDown (other available animation transitioning types are UIViewAnimationTransitionFlipFromLeft, UIViewAnimationTransitionFlipFromRight, and UIViewAnimationTransitionCurlUp)

Press Command-r to test the application again. This time, watch what happens when you press the Display SecondView button (see Figure 16).

Of course, you want the animation to work both ways, so back in Xcode, add the following lines to the SecondViewController.m file:

-(IBAction) btnReturn:(id) sender {    [UIView beginAnimations:@"flipping view" context:nil];    [UIView setAnimationDuration:1];    [UIView setAnimationCurve:UIViewAnimationCurveEaseIn];    [UIView setAnimationTransition: UIViewAnimationTransitionCurlUp       forView:self.view.superview cache:YES];        [self.view removeFromSuperview];    [UIView commitAnimations];}

 
Figure 17. Flipping Back: The figure shows the flipping animation in action on the second view.

Press Command-r to test the application. When you press the Return button in the second view, the second view now has the page-flip transition as well (see Figure 17).

Passing Data Between Views

Sometimes you need to pass data from one view to another. The easiest way is to create a property on the target view and set (or retrieve) that property from the calling view.

Here’s an example. Double-click the VCExampleViewController.xib file and add a DatePicker view to the View window (see Figure 18).

 
Figure 18. Enhancing the View: Add a DatePicker view to the first View.

In the VCExampleViewController.h file, create an outlet for this DatePicker view and then expose it as a property:

#import @interface VCExampleViewController : UIViewController {    //---outlet for the DatePicker view---    IBOutlet UIDatePicker *datePicker;}//---expose this outlet as a [email protected] (nonatomic, retain) UIDatePicker *datePicker;-(IBAction) displayView:(id) sender;@end

In the VCExampleViewController.xib window, control-click and drag the File’s Owner Item to the DatePicker view and then select datePicker.

In the SecondViewController.h, create an object of type UIDatePicker and then expose it as a property:

#import @interface SecondViewController : UIViewController {    //---object of type UIDatePicker---    UIDatePicker *selectedDatePicker;}//---expose the object as a [email protected] (nonatomic, retain) UIDatePicker *selectedDatePicker;-(IBAction) btnReturn:(id) sender;@end

In the SecondViewController.m file, add the following lines (in bold) to the viewDidLoad method:

#import "SecondViewController.h"@implementation [email protected] selectedDatePicker;- (void)viewDidLoad {    //---display the date and time selected in the previous view---    NSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease];    [formatter setDateFormat:@"MMM dd, yyyy HH:mm"];        UIAlertView *alert = [[UIAlertView alloc]                              initWithTitle:@"Date and time selected"                              message:[formatter stringFromDate:selectedDatePicker.date]                              delegate:self                              cancelButtonTitle:@"OK"                              otherButtonTitles:nil];    [alert show];    [alert release];        [super viewDidLoad];}- (void)dealloc {    //---release the memory used by the property---    [selectedDatePicker release];    [super dealloc];}

Finally, in the VCExampleViewController.m file, add the line shown in bold:

#import "VCExampleViewController.h"#import "SecondViewController.h" @implementation VCExampleViewControllerSecondViewController *secondViewController;@synthesize datePicker;-(IBAction) displayView:(id) sender{secondViewController = [[SecondViewController alloc]                                 initWithNibName:@"SecondView"                                 bundle:nil];    //---set the property of the second view with the DatePicker view in the current view---    secondViewController.selectedDatePicker = datePicker;

 
Figure 19. Passing Values Between Views: The second view now displays the date and time selected from the DatePicker in the first view.
     [UIView beginAnimations:@"flipping view" context:nil];    [UIView setAnimationDuration:1];    [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];    [UIView setAnimationTransition:          UIViewAnimationTransitionCurlDown           forView:self.view cache:YES];        [self.view addSubview:secondViewController.view];    [UIView commitAnimations];    }

Press Command-r to test the application. Select a date and time in the DatePicker view and press the Display SecondView button. The second view will now display the date and time selected in the first view (see Figure 19).

You’ve seen how view controllers work, and how to add a new view controller to your iPhone application. You have also seen how to switch between two views and how to animate the transitioning process. Finally, you explored how to pass values between two views. As these operations form the basics of iPhone programming, you should be well on your way to creating your own iPhone applications.

Share the Post:
Share on facebook
Share on twitter
Share on linkedin

Related Posts