Creating a Simple iPhone Table View Application

An Overview of the Table View

Table Views present the user with data in a list format and are represented by the UITableView class of the UIKit framework. The data is presented in rows, whereby the content of each row is implemented in the form of a UITableViewCell object. Each table cell can display a text label (textLabel), a subtitle (detailedTextLabel) and an image (imageView). More complex cells can be created by either adding subviews to the cell, or sub classing UITableViewCell and adding your own custom functionality.

  The Table View Delegate and dataSource

Each table view in an application needs to have a delegate and a dataSource associated with it. The dataSource implements the UITableViewDataSource protocol, which basically consists of a number of methods that define title information, how many rows of data are to be displayed, how the data is divided into different sections and, most importantly, supplies the table view with the cell objects to be displayed. The delegate implements the UITableViewDelegate protocol and provides additional control over the appearance and functionality of the table view including detecting when a user touches a specific row, defining custom row heights and indentations and also implementation of row deletion and editing functions.

  Table View Styles

Table views can be configured to use either plain or grouped style. In the grouped style, the rows are grouped together in sections that are represented by rounded rectangles. For example, the following figure shows a table view configured to use the grouped style:

The iPhone Table View in grouped style mode

In the case of the plain style, the items are listed using the full width of the display:

The iPhone Table View in plain style mode

Table Views using plain style can also be indexed, whereby rows are organized into groups according to specified criteria, such as alphabetical or numerical sorting.

  Table View Cell Styles

In addition to the style of the Table View itself, different styles may also be specified for the individual table cells. The iPhone SDK currently supports four different cell styles:

  • UITableViewCellStyleDefault – only the labelText in black and left aligned.
  • UITableViewCellStyleSubtitle – labelText in black and left aligned with the detailLabeltext positioned beneath it in a smaller font using a gray foreground.
  • UITableViewCellStyleValue1 – labelText in black left aligned and the smaller detailLabelText in blue, on the same line and right aligned.
  • UITableViewCellStyleValue2 – labelText in blue on left side of cell, right aligned and detailedLabelText on right of cell, left aligned and black.

The style of a particular cell is specified when the cell object is created and will be covered in detail in a later section.

  Setting up the Project

For the purposes of this chapter we will be creating a very simple iPhone application that contains a single Table View.
Begin by launching Xcode and selecting the option to Create a new Xcode Project. In the New Project window, select View-based application, click Choose… and name the project TableExample.

  Adding the Table View Component

Not surprisingly, the application we are creating is going to require an instance of the Table View component. Double click on the TableExampleViewController.xib file to launch the Interface Builder tool and drag a Table View instance from the Data Views section of the Library window (Tools -> Library or Command + L) onto the View window:

A Table View object within Interface Builder

  Making the Delegate and dataSource Connections

For the sake of simplicity, we are going to use our view controller class as both the dataSource and delegate for our application. This means that in our view controller we are going to need to implement the numberofRowsInSection and cellForRowAtIndexPath methods of the UITableViewDataSource protocol in the view controller. Before doing so, however, we need to connect the dataSource and delegate outlets of the Table View component to the view controller. To achieve this, make sure that the Table View component is selected in the Interface Builder View window and open the Connections Inspector (Tools -> Connections Inspector or Command + 2). In the Connections Inspector window, click in the small circle to the right of the dataSource outlet and drag the blue line to the File’s Owner icon located in the TableExampleViewController.xib document window. Once the connection is established, repeat this task for the delegate outlet. The connections should now be displayed as follows:

Table View delegate and dataSource connections established in Interface Builder

Now that the connections have been established, save the file and exit from Interface Builder.

  Implementing the dataSource

In order to bring our table view application to life we need to implement two dataSource methods in our view controller. Before doing so, however, we need to create the data itself. In this example, we are going to create NSArray object and initialize it with some strings. In the main Xcode project window, select the TableExampleViewController.h file and modify it in the editing pane to declare the array:

#import <UIKit/UIKit.h>@interface TableExampleViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>{        NSArray *colorNames;}@property (nonatomic, retain) NSArray *colorNames;@end

Note the references to UITableViewDelegate and UITableViewDataSource in the above code. These are included to notify the Objective-C compiler that the class implements these two protocols. Consequently, if we fail to implement the mandatory methods required by these protocols the compiler will notify us with a warning. If this line is omitted from the class declaration the code will still compile, but we not be warned if we have failed to implement any methods. The only indication we will get will the application crashing at run time. For this reason, including these declarations is generally considered to be good programming practice.
Next, edit the TableExampleViewController.m class implementation file to synthesize access to the array:

#import "TableExampleViewController.h"@implementation TableExampleViewController@synthesize colorNames; ...@end

Now that we have declared our array we need to initialize it with some data when the view is loaded. In order to achieve this we will override the viewDidLoad method. Scroll down the TableExampleViewController.m file until you find the template method, uncomment it by removing the /* and */ markers and modify the method as follows:

// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.- (void)viewDidLoad {    [super viewDidLoad];    self.colorNames = [[NSArray alloc] initWithObjects:@"Red", @"Green",                     @"Blue", @"Indigo", @"Violet", nil];}

Having allocated memory to our array and initialized it, the next task is to make sure the memory gets released when the array is no longer required. To do so it is necessary to add code to the viewDidUnload and dealloc methods:

- (void)viewDidUnload {        // Release any retained subviews of the main view.        // e.g. self.myOutlet = nil;        self.colorNames = nil;}- (void)dealloc {    [colorNames release];    [super dealloc];}

With our data constructed all we need to do now is implement the numberOfRowsInSection and cellForRowAtIndexPath methods in order to conform to the minimum requirements of the UITableViewDataSource protocol. We will begin by implementing the numberOfRowsInSection method which is called by the Table View to identify how many rows are to be displayed. Since our data is held in an array we can simply return the number of array elements to satisfy this requirement so add the following method to your TableExampleViewController.m file:

// Customize the number of rows in the table view.- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {        return [self.colorNames count];}

Next, the cellForRowAtIndexPath method needs to be implemented:

// Customize the appearance of table view cells.- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {    static NSString *CellIdentifier = @"Cell";    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];    if (cell == nil) {        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];    }        // Configure the cell.        cell.textLabel.text = [self.colorNames objectAtIndex: [indexPath row]];    return cell;}

In the above method everything, with the exception of the following line, is standard boilerplate code that you can reuse every time you need to implement this particular method:

cell.textLabel.text = [self.colorNames objectAtIndex: [indexPath row]];

The method begins by creating a cell identifier. Next, an attempt is made to reuse an existing cell that may have scrolled off the screen and is therefore available for use as the currently requested cell. If no previous cell is available for use then a new one is created using the UITableViewCellStyleDefault style. The cellForRowAtIndexPath method is passed as an argument an object of type NSIndexPath from which we are able to extract the row number for which the cell is being requested by the table view. This row number is used, in turn, to extract the corresponding element from our colorNames array and assign it to the textLabel property of the cell object.

  Building and Running the Application

Once the code has been implemented for the application, build and run it by clicking on the Build and Run button located in the toolbar of the Xcode main project window. Once compiled the application should run in the simulator and appear as illustrated in the following figure:

Example iPhone Table View app running in simulator

  Adding Table View Images and Changing Cell Styles

Now that we have created a simple table view example we can look at extending our code to change the cell style. In so doing we will make use of the image and detailed text properties of the cell object to add images and subtitles to each row of the view.The first step is to add an image to the resources of our project. If you already have an image file that is suitable for this purpose feel free to use it in this example. Alternatively, we can pick up an image from the Mac OS X system on which Xcode is running. To add an image file to the application resources, right click on the Resources entry in the Groups and Files panel of the main Xcode project window. From the resulting menu, select the Add -> Existing Files… option. In the resulting file selection panel navigate to and select your pre-existing image file. Alternatively, enter apple.png into the search field and press Enter. The apple.png file should appear in the file list from where it can be selected:

Adding an image file to the resources of an Xcode project

Once the appropriate image file has been selected, click on the Add button to add the image to the resources. On the following panel accept the default settings and click Add once again.
Now that the image is included in the project resources it is time to add some code to the cellForRowAtIndexPath method in the TableExampleViewCrontoller.m file. All we need to do in this file is add some code to create a UIImage object from the image file and assign it to the imageView property of the cell object. With these changes made, the method should read as follows:

// Customize the appearance of table view cells.- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {    static NSString *CellIdentifier = @"Cell";    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];    if (cell == nil) {        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];    }        // Configure the cell.        UIImage *cellImage = [UIImage imageNamed:@"apple.png"];        cell.imageView.image = cellImage;        cell.textLabel.text = [self.colorNames objectAtIndex: [indexPath row]];        return cell;}

Next, we want to add a subtitle to the text of each cell. This is achieved by assigning a string to the cell object’s detailTextLabel text property. Note also that the code currently selects the UITableViewCellStyleDefault cell style which does not display the detailText. It will also be necessary, therefore to change the cell style to UITableViewCellStyleSubtitle . With all of these changes implemented, the method now reads as follows:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {    static NSString *CellIdentifier = @"Cell";    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];    if (cell == nil) {        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];    }        // Configure the cell.        UIImage *cellImage = [UIImage imageNamed:@"apple.png"];        cell.imageView.image = cellImage;        NSString *colorString = [self.colorNames objectAtIndex: [indexPath row]];        cell.textLabel.text = colorString;        NSString *subtitle = [NSString stringWithString: @"All about the color "];        subtitle = [subtitle stringByAppendingFormat:colorString];        cell.detailTextLabel.text = subtitle;        return cell;} 

Once the changes have been made to the code, build and run the application. When the simulator starts up the table view should appear with images and subtitles as shown in the following figure:

iPhone table view with subtitles and images

3 Responses

  1. I’m curious to find out what blog platform you are utilizing? I’m having some minor security problems with my latest website and I would like to find something more risk-free. Do you have any suggestions?

  2. I was curious if you ever considered changing the structure of your website? Its very well written; I love what youve got to say. But maybe you could a little more in the way of content so people could connect with it better. Youve got an awful lot of text for only having one or 2 images. Maybe you could space it out better?

  3. Does your site have a contact page? I’m having problems locating it but, I’d like to shoot you an e-mail. I’ve got some ideas for your blog you might be interested in hearing. Either way, great site and I look forward to seeing it expand over time.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>