Cocoa Programming for Mac OS X - Aaron Hillegass [118]
UITableViewController
Table views, found in nearly every OS application from the iPod to Stocks, provide a highly customizable way of displaying ordered sets of information to the user. After working with table views for a bit, you will quickly see that most of the attractive user interfaces in your favorite apps are simply table views.
UITableViewController is a subclass of UIViewController specifically designed to manage a UITableView. UITableViewController automatically creates the table view it manages. It is also the data source and delegate for the table view, so your UITableViewController subclass must override the appropriate methods to get data on the table view. Consistent with data source and delegation methods in other Apple frameworks, you do not give the table view data whenever you want. When ready to display data, the table view will ask you for the necessary information.
The Xcode template for a UITableViewController subclass includes the necessary UITableViewDataSource methods. Fill them in for ScheduleViewController.m:
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [classes count];
}
- (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];
}
ScheduledClass *c = [classes objectAtIndex:[indexPath row]];
NSString *details = [NSString stringWithFormat:@"%@ - %@",
[dateFormatter stringFromDate:c.begin],
c.location];
[[cell textLabel] setText:[c name]];
[[cell detailTextLabel] setText:details];
return cell;
}
UITableView works very similarly to view-based table views in Cocoa. The table view asks its data source to provide a UITableViewCell for each row. The data source obtains a view cell (we will talk about that in a moment) and populates its controls (labels, in this case) with the data values from the model.
Note that the view cell itself is obtained in one of two ways: through a call to dequeueReusableCellWithIdentifier: or by creating one outright. UITableView takes advantage of the fact that most table-view cells will have the same layout. Thus, when the user scrolls in the table such that a row is no longer visible, the cell for that row is made available for reuse. In this way, the UITableView keeps memory usage low and minimizes time spent configuring the view cells. The table view uses identifiers to look up cells of a certain type. Thus, you can still take advantage of the cell reuse by using unique identifiers for distinct cell layouts.
Pushing View Controllers
ScheduleViewController is ready to display schedule data in its table. We need to modify RootViewController to obtain the schedule data and then cue ScheduleViewController to display it.
In RootViewController.m, import ScheduleFetcher.h and ScheduleViewController.h, and set the title of the navigation item:
#import "RootViewController.h"
#import "ScheduleFetcher.h"
#import "ScheduleViewController.h"
@implementation RootViewController
- (id)initWithNibName:(NSString *)nibNameOrNil
bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
[[self navigationItem] setTitle:@"Ranch Forecast"];
}
return self;
}
Now we are ready to fill in the code for the fetchClasses: action. We will use ScheduleFetcher, which we copied directly from the Cocoa version of this application, to obtain the results. The block we supply will be called once the results have been received or if an error has