iPhone Development 101

iPhone 101

Code Tips

Resources

Links

Subscribe

TwitterRSSE-mail

More

Learn iPhone Programming:
View Controllers

This tutorial was written for Xcode 3.2; it's outdated now. For a more up-to-date tutorial, check out Apple's App Development Tutorial to learn how to write iOS apps. There are also lots of other excellent books and online tutorials you can learn from.

I'll still be posting code tips and shortcuts to idev101; click here for the index. If you'd like to get updates, follow me on Twitter, or by RSS or E-mail.

UIViewController is a specialized class for managing views. You will usually create a view controller for each full-screen view in your app. The view controller will contain all of the IBOutlets and IBAction methods for the view.

To create a view controller, create a new file in Xcode (File menu -> New File, or ⌘N). Select Cocoa Touch Classes in the left frame, and the UIViewController subclass on the right. Click Next and name your new file MyViewController.m. (You can name it anything, but common practice is to use ViewNameController for the class name.) Check the boxes for "Also create MyViewController.h" and "Add to Project" (Second project).

Next add the IBOutlet variables to MyViewController.h. You need one for the label (an instance of UILabel), button (UIButton), and text view (UITextView):

#import <UIKit/UIKit.h>

@interface MyViewController : UIViewController {
    IBOutlet UILabel *nameLabel;
    IBOutlet UIButton *imgButton;
    IBOutlet UITextView *infoText;
}

@end

Also add an IBAction method that will be called when the button is clicked:

- (IBAction)showImage:(id)sender;

Remember to also implement the showImage method in MyViewController.h. For now just make it an empty method:

- (IBAction)showImage:(id)sender {
}

Save the files, then double-click on MyView.xib to switch back to Interface Builder. Notice the document window has three objects: two orange cube icons (for File's Owner and First Responder), and one square icon representing the view itself. This is where you'll associate the view with its controller. Click on the File's Owner icon, then look at the identity tab (⌘4) in the inspector. Change the Class pull-down from NSObject to MyViewController:

Save the file. Go ahead and make connections for all of the IBOutlets and IBActions by control-dragging between your UI objects and the File's Owner icon.

Connecting the View Controller to its View

There's one more connection you need to make. The UIViewController class has a view property which points to the view itself. Control-drag from the File's Owner icon to the view icon to connect it. (If you forget this part, your app will crash with the error "UIViewController loaded the "MyView" nib but the view outlet was not set.")

Adding the View to the Window

Save MyView.xib and switch back to Xcode. At this point you could build and run the project, but you'll only see an empty window, not your new view. That's because you haven't added the view to the window. To add it, your code needs to create an instance of MyViewController, then add the controller's view to the window by calling the window's addSubview method.

The window object is defined in the app delegate class, so that's where you'll create the new instance. Edit SecondAppDelegate.m, and import the header file for the MyViewController class:

#import "MyViewController.h" 

Next you'll create an instance of MyViewController in the applicationDidFinishLaunching method. Since we're using a xib file with this controller, you should initialize the object using the initWithNibName method:

MyViewController *controller = [[MyViewController alloc] initWithNibName:@"MyView" bundle:nil];

Finally, add the controller's view as a subview of the window:

[window addSubview:[controller view]];

Here's what the completed applicationDidFinishLaunching method should look like:

- (void)applicationDidFinishLaunching:(UIApplication *)application {    

    // Override point for customization after application launch
    [window makeKeyAndVisible];
    
    MyViewController *controller = [[MyViewController alloc] initWithNibName:@"MyView" bundle:nil];
    [window addSubview:[controller view]];
}

Save it and click "Build and Run" to view your project. You'll notice a 20-pixel gap between the bottom of the view and the bottom of the window; this means the view's frame is off. For now, you can fix it by adding this line just before the addSubview line:

[controller.view setFrame:[[UIScreen mainScreen] applicationFrame]];

This sets the new view's frame (or dimensions) to the same size as the application frame, which is shifted down 20 pixels to account for the status bar. You can read more about frames and sizes here.

Other View Controller Methods

If you look at the source code for MyViewController.m, you'll notice several methods that were created automatically when you created the file. You can uncomment these if you'd like to customize them; otherwise you can just delete them from the source code.

Open the UIViewController Class Reference and look at the list of instance methods for this class. There are a number of methods you'll commonly be implementing in your custom view controllers:

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil

initWithNibName is a special initializer that loads the specified xib file when the controller instance is created. If your controller has any custom variables that need to be set, this is a good place to do it.

- (void)viewDidLoad

viewDidLoad is called after the view has finished loading. This usually only happens once, but in certain low-memory situations it's possible for a hidden view controller to release its view to save memory. In that case viewDidLoad would be called again the next time the view appears. This method is a good place to add any programmatically-created UI elements, because they only exist if the view exists.

All of these methods are called before or after a view appears or disappears:

- (void)viewWillAppear:(BOOL)animated       // before the view appears

- (void)viewDidAppear:(BOOL)animated        // after the view appears 

- (void)viewWillDisappear:(BOOL)animated    // before the view disappears

- (void)viewDidDisappear:(BOOL)animated     // after the view disappears, but before the controller 
                                            // is released

If you need to do any customization of the view after it appears, or save any data before the view goes away, these methods are the place to do it. Note that the documentation says "if you override this method, you must call super at some point in your implementation." This means you have to call the same method name on the parent (or super class):

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];     // call the parent's viewDidAppear method
    NSLog(@"myview did appear!");
}

Create a viewDidAppear method for your view controller. Have the method change the text on the label to say "Bluebonnet", and the text in the text view to say "A native Texas wildflower."

Additional References


TopHomeContents