Cover by Alasdair Allan

Stay ahead with the world's most comprehensive technology and business learning platform.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, tutorials, and more.

Start Free Trial

No credit card required

O'Reilly logo

Fundamental iPhone Design Patterns

When you write code you’re probably already using patterns, although possibly you’re doing so without realizing it. A design pattern is just a reusable solution, a template, for how to approach commonly occurring problems. A pattern is not code, but instead describes how you should model the application in terms of the classes that are used, and how they should structure the interactions and relationships between these classes.

The Cocoa Touch framework underlying your iPhone applications is based on one of the oldest design patterns, the Model-View-Controller (MVC) pattern, which dates from the 1970s. The MVC pattern is used to separate the program logic from the UI, and is the generally accepted way to build iPhone applications. As it is used so extensively inside Apple’s own frameworks, including the UIKit framework, it would be quite hard to write an iPhone application without using this pattern in your implementation. While you could write an iPhone application without referencing the MVC pattern, it is enormously difficult to fight the underlying frameworks; you should instead work with them. Attempting to write iPhone applications while ignoring the underlying MVC patterns is a pointless exercise in make-work.

The Model-View-Controller Pattern

The MVC pattern divides your application into three functional pieces:

Model

The model manages the application state (and associated data) and is usually persistent. It is entirely decoupled from the UI or presentation of the application state to the user.

View

The view is what the user sees, and it displays the model for the user. It allows the user to manipulate it and respond and generate events. In iPhone applications, the view is normally built inside Interface Builder rather than programmatically.

Controller

The controller coordinates updates of the view and the model when user interaction with the view makes changes to the model, and vice versa. This is typically where most of the application logic lives.

We implemented our Hello World application from Chapter 3 using this pattern. We created the view using Interface Builder, and the HelloWorldViewController class managed the view. The application was too simple to require an explicit class to manage the application’s state; effectively, the model was embedded in the ViewController class. If we were strictly adhering to the design pattern, we would have implemented a further class that our sayHello: method would have queried to ask what text should have been displayed.

The model class is usually a subclass of NSObject and has a set of instance variables and associated accessor methods, along with custom methods to associate the internal data model.

Views and View Controllers

I’ve talked about both views and view controllers quite a lot, and while so far we’ve built our views in Interface Builder and then handled them using our own view controller code, that isn’t the only way to build a view. You can create views programmatically—in fact, in the early days of iPhone development you had to do things that way.

However, Interface Builder has made things a lot easier, and I recommend that in most cases you build your views using it if you can. When you used Interface Builder to construct your view you edited a NIB file, an XML serialization of the objects in the view. Using Interface Builder to create these objects, and to define the relationship between them and your own code, saves you from writing large amounts of boilerplate code that you would otherwise need to manage the view.

If you want to create your view manually, you should override the loadView: method of your view controller class, as this is the method the view controller calls when the view property is requested but is currently set to nil. Don’t override this method if you’ve created your view using the initWithNibName: method, or set the nibName or nibBundle properties. If you’re creating your view manually and you do override this method, however, you must assign the root view you create to the view property of your view controller class:

-(void) viewDidLoad {
    UIView* view = [[UIView alloc] initWithFrame:CGRectMake(0,0,320,480)];
        .
        .
        .
    self.view = view;
    [view release];
}

Your implementation of this method should not call [super viewDidLoad], as the default implementation of this method will create a plain UIView if no NIB information is present and will make this the main view.

The Delegates and DataSource Pattern

I talked briefly about delegates in Chapter 3. An object that implements a delegate protocol is one that acts on behalf of another object. To receive notification of an event to which it must respond, the delegate class needs to implement the notification method declared as the delegate protocol associated with that event. The protocol may, and usually does, specify a number of methods that the delegate class must implement.

Data sources are similar to delegates, but instead of delegating control, if an object implements a DataSource protocol it must implement one or more methods to supply data to requesting objects. The delegating object, typically something such as a UITableView, will ask the data source what data it should display; for instance, in the case of a table view, what should be displayed in the next UITableViewCell when it scrolls into the current view.

Declaring that a class is a data source or a delegate flags the object for Interface Builder so that you can connect the relevant UI elements to your code. (We’ll be talking about UITableView in Chapter 5.) To declare that AnObject was both a table view data source and a delegate, we would note this in the @interface declaration:

@interface AnObject: UIViewController <UITableViewDataSource,
                                       UITableViewDelegate> {
   ...
}

This would mean that the AnObject object, a UIViewController, is responsible for both populating the table view with data and responding to events the table view generates. Another way to say this is that this object implements both the UITableViewDataSource and the UITableViewDelegate protocols.

At this point, you would use Interface Builder, and we’ll be doing that in the next chapter when we build a table-view-based application to connect the UITableView in our view to the data source and delegate object in our code.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, interactive tutorials, and more.

Start Free Trial

No credit card required