Most business applications tend to show one or more rows of data items, be they stock prices, status reports, time sheet entries, inventory levels, or the like. So the use of tables is a pervasive need for mobile business applications, and developers using iOS as well as other mobile environments must master the details of presenting rows of data in an attractive, usable format.
Fortunately, Cocoa Touch--the object-oriented framework used in programming for Apple devices such as the iPhone, iPod Touch, and iPad--provides classes that display data in a compact, tabular format. UITableView, for instance, arranges data into a hierarchic structure of lists, with each one presented as a table on the screen. Other supporting classes and methods help users navigate easily through these tables, letting them quickly drill down through a complex data set to the desired information.
UITableView is good at managing and displaying information and often serves as the workhorse in data-centric applications. But information on using UITableView is scattered throughout volumes of documentation in the Apple iOS software development kit. To simplify things, I've consolidated this information in this introduction to UITableView and its related classes.
Terminology And Style
In the abstract, table data is presented as rows of content that can be formatted in a specific style. Exactly what constitutes a row and a column, though, is a looser concept on mobile devices than it is on the desktop. An iOS table row is a horizontal strip of content drawn across the width of the screen. The content of a row can be a mix of text and graphics, and you use points to specify a row's height. Because a row spans the width of the screen, a table displays only one column of information.
Rows of related content can be grouped into sections. Sections have distinctive header strips that appear at the top of each group and include a title. An optional footer can appear below each group and also has a title. Titles can consist of strings or graphics. As with rows, you can specify the height of headers and footers. The entire table can also have its own optional header and footer.
iOS tables come in two styles: plain and grouped. For the plain style, a table consists of section headers, followed by rows of content displayed as lists. For the grouped style, the sections occupy distinct screen regions, with the header and footer content appearing above and below them (see figure, p. 31).
When you first create a table, you specify its style, either directly in the code or in Interface Builder. Once set, a table's style can't be changed.
Table rows, which are also called cells, have four predefined styles: default, style1, style2, and subtitle. The styles vary slightly in the number of built-in text fields they offer and whether an optional image is displayed. Different styles can appear in a table, and the style can be changed on the fly.
Cells can also be customized to present additional text labels and images, or present controls such as sliders, buttons, and switches. For example, in the figure on p. 31 the grouped table has a cell with a switch and another that has a segment control.
A key class for managing an iOS device screen is the UIView. It's responsible for painting content on the screen and capturing user events (typically touches). For more on how to use the UIView class, see "The iPhone Isn't Easy," infor mationweek.com/1292/ddj/noteasy.
I mention the UIView class here because UITableView and UITableViewCell are subclasses of it. Therefore, they inherit the ability to display content and respond to touch events. However, these classes don't store data. They only display it and let users interact with the app's data repository, also known as the app's data model.
UITableView is responsible for implementing a table's layout and certain behaviors. It uses cell objects to organize and display the data. It also is scrollable like UIScrollView, but only vertically.
The UITableViewCell class is responsible for displaying a row and its content. This class serves as a template that clones as many instances of a cell as is required to make up a section. In this sense, UITableViewCell functions similarly to a Java factory method. Each cell can have a different style and displays the information that it references in the data model. As mentioned earlier, a cell can display text, images, and controls. Cells are complex objects with many built-in views, including several content-specific views, as well as a background view and an accessory view. The accessory view displays controls and optional images that assist in navigating to another screen.
In iOS parlance, a table protocol defines method declarations and the desired responses when these methods are invoked. It's up to the developer to assign a delegate object that implements the protocol. An Objective-C protocol therefore functions like a Java interface. The iOS runtime is made aware that a class is a delegate object by the addition of a suitable protocol declaration in the class' header file.
Tables use two protocols: UITableViewDataSource_Protocol and UITableViewDelegate_Protocol. The UITableViewDataSource_Protocol gets information for UITableView about table layout and how to supply data to it for display. For table layout, this protocol defines two required methods. The first method, numberOfRowsInSection, queries the app about the number of rows a section has. The second, cellForRowAtIndexPath, retrieves a specific cell in the table so that it can be matched up to its data source and the data displayed.
The UITableViewDelegate_Protocol describes how the table behaves and its appearance. This protocol is used to customize the appearance of headers and footers, modify a cell's height, and specify a background color or image. All methods in this protocol are optional.
A UITableViewController class is a variant of the UIViewController class, which is designed to manage a table. It packages housekeeping functions, the stub routines for the data source, and delegate protocol methods into one convenient view controller class. This design allows the table's event handling, data display, data updates, and custom behavior to be contained in one omnibus object. UITableViewController also performs duties such as loading the table's data, flashing the scroll indicators, and clearing the selection choice. It provides access to the table view's elements and properties.
A final class, NSIndexPath, has little to do with tables but is crucial to their operation. It describes a path to a node in a tree of arrays. Recall that tables are organized as a hierarchy of lists, where each list corresponds to an array. An instance of NSIndexPath provides the section and row information that references a specific cell and can be used to also reference its data. Many table view methods described here use NSIndexPath instances as arguments, or they return results as an NSIndexPath. For more information on each class, consult the iOS software development kit documentation.
When writing code, the first decision is whether to use a UIViewController to manage the instance of UITableView, or a UITableViewController. The UIViewController choice gives you fine-grained control over every aspect of the table's appearance and operation. However, that control comes at a price: You have to manage every detail of the table's operation, such as assigning and implementing the protocol delegate objects.
In contrast, UITableViewController manages a lot of details for you by assigning itself as the delegate object for both protocols. It also provides some housekeeping routines. The trade-off is that some flexibility in table design is lost because this class implements certain default behaviors. I've used UITableViewControllers for data display and in many cases was able to customize a table's appearance without too much effort. Unless you require an extremely customized user interface, I'd recommend starting with a UITableViewController.
The source code for how to do this--as well as additional information, including screen shots of the table functions--can be found at informationweek.com/1292/ ddj/table. These examples only scratch the surface of what's possible with iOS tables. You can edit and tinker with them. Try changing a cell's style, for example. Or with Interface Builder, change the table's property from plain to grouped and see what happens. Experimenting is the best way to expand your knowledge of how iOS table design is done.
Tom Thompson is head of Proactive Support for embedded products at Freescale Semiconductor. The views don't represent Freescale's positions, strategies, or opinions. Write to us at [email protected]