Table View Controller in iPad

Table views are most often used in conjunction with Navigation Controllers to present a list of choices to the user, then push a new view controller depending on the choice the user made. In this blog, we’ll demonstrate how to set up a table view holding a list of colors, then push a view controller having a background color corresponding to the selected color in the table view. So, let’s get started!

Start up Xcode, select “Create a new Xcode project,” and select the Empty Application template. Name the project “TableView” and choose options as shown:

Click Next, choose a location to save the project, and click Create.

After the project has been created, select the AppDelegate.m file, then right-click it and select “New File…” from the popup menu. (Selecting the AppDelegate.m file first will place the new files immediately after the selected file.) We will be creating a new UITableViewController class. Choose the Objective-C class template, click Next, and name the new file RootViewController. Make sure it is a subclass of UITableViewController, and select options as shown:

Click Next and save the new files to the default location by clicking Create. Now repeat the above process, this time creating a new UIViewController class called ColorViewController with the following options:

When you are finished, the navigation panel in Xcode should look like this:

Now we’ll set up the AppDelegate to instantiate the RootViewController and a navigation controller, make the RootViewController object the root view controller of the navigation controller, and add the navigation controller’s view as a subview of the main window. Here is AppDelegate.h:

#import <UIKit/UIKit.h>
#import "RootViewController.h"

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) UINavigationController *navController;
@property (strong, nonatomic) RootViewController *rootViewController;

@end

We’ve imported the RootViewController class, and also made properties for both the RootViewController and a UINavigationController object called navController. Let’s see how we set this up by looking at the AppDelegate.m file:

#import "AppDelegate.h"

@implementation AppDelegate

@synthesize window = _window;
@synthesize navController = _navController;
@synthesize rootViewController = _rootViewController;

(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // Override point for customization after application launch.
    self.rootViewController = [[RootViewController alloc] initWithNibName:nil bundle:nil];
    self.navController = [[UINavigationController alloc] initWithRootViewController:self.rootViewController];
   
    [self.window addSubview:self.navController.view];
    [self.window makeKeyAndVisible];
    return YES;
}

As always, we first synthesize the properties, giving aliases to the iVar names so that we’re not tempted to access the properties without using “self.” The only changes we’re making to this file occur in the application: didFinishLaunchingWithOptions: method; the rest of the file is not shown here to save space.

We instantiate self.rootViewController from the RootViewController class. The nib name “nil” here refers to the xib file that is already associated with the class: RootViewController.xib. A bundle of nil refers to this application’s bundle.

Next, the navController object is instantiated, and initialized with rootViewController as it’s root view controller. Finally, the navController’s view is added to the main window as a subview, and the main window is made key and visible.

If we run the application now, it will display an empty table view, because we’ve not told the RootViewController what data to display, or how to display it. Open the RootViewController.h file, and make changes as shown here:

#import <UIKit/UIKit.h>
#import "ColorViewController.h"

@interface RootViewController : UITableViewController

@property (nonatomic, strong) NSArray *tableCellContent;

@end

Notice that we’ve imported the header for ColorViewController, and also made a property of an NSArray object called tableCellContent.

UITableViewController objects adopt two protocols: UITableViewDelegate and UITableViewDataSource. The required delegate methods are already provided in a table view controller’s implementation file as “stubs,” it is up to us to fill them out with useful code.

Open RootViewController.m. You will see several methods. The first method we will make changes to is viewDidLoad:

(void)viewDidLoad
{
    [super viewDidLoad];

    // Uncomment the following line to preserve selection between presentations.
    // self.clearsSelectionOnViewWillAppear = NO;
   
    self.tableCellContent = [NSArray arrayWithObjects:@"red", @"green", @"blue", @"yellow",
                             @"cyan", @"white", @"black", @"gray", nil];
   
    // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
    // self.navigationItem.rightBarButtonItem = self.editButtonItem;
}

Here, we set up the tableCellContent array with eight NSString objects containing the names of colors. An NSArray is always set up with the last object set to nil: make sure that you also include this value!

Now alter the numberOfSectionsInTableView: and tableView: numberOfRowsInSection: methods:

(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    // Return the number of sections.
    return 1;
}

(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // Return the number of rows in the section.
    return self.tableCellContent.count;
}

In this demo, our table view will have only one section, so we simply return 1 from the numberOfSectionsInTableView: method. But in the tableView: numberOfRowsInSection: method, we return the count of objects in the tableCellContent array: this will allow the table view controller to have (initially) the proper number of rows.

In order for the table view controller to display its cells, we must alter the tableView: cellForRowAtIndexPath: method:

(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];
    }
   
    // Configure the cell…
    cell.textLabel.text = [self.tableCellContent objectAtIndex:indexPath.row];
    return cell;
}

A table view contains a number of reusable cells. Initially, the table view contains no cells, so we must instantiate them ourselves. But as cells are scrolled on and off the table view, the system will reclaim them from the queue of reusable cells. The dequeueReusableCellWithIdentifier: method returns an already used cell that is not currently being displayed in the view.

But if there is not a reusable cell (if cell == nil), we must create one. Here, we create an instance of UITableViewCell with the UITableViewCellStyleDefault style. This statement will add a cell to the queue of reusable cells.

Next, we set the cell’s textLabel’s text property to the object in the tableCellContent array that has the index of indexPath.row. The indexPath is an instance of NSIndexPath, which represents a path to a specific node in a collection of arrays. By using indexPath.row, we can get an integer corresponding to the index for a particular cell in the table view, and use it as an index into the tableCellContent array. After setting the cell’s text, we return the cell.

If we run the application now, the table view will show text in each of its first eight cells, corresponding to the text in the tableCellContent array:

But tapping a cell in the table view will have no result: to set that up, we must alter a fourth delegate method: tableView: didSelectRowAtIndexPath:

(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    // Navigation logic may go here. Create and push another view controller.
   
     ColorViewController *colorViewController = [[ColorViewController alloc] initWithNibName:nil bundle:nil];
    // array is: @"red", @"green", @"blue", @"yellow", @"cyan", @"white", @"black", @"gray"
    UIColor *bgColor;
    switch (indexPath.row) {
        case 0:
            bgColor = [UIColor redColor];
            break;
        case 1:
            bgColor = [UIColor greenColor];
            break;
        case 2:
            bgColor = [UIColor blueColor];
            break;
        case 3:
            bgColor = [UIColor yellowColor];
            break;
        case 4:
            bgColor = [UIColor cyanColor];
            break;
        case 5:
            bgColor = [UIColor whiteColor];
            break;
        case 6:
            bgColor = [UIColor blackColor];
            break;
        case 7:
            bgColor = [UIColor grayColor];
            break;
           
        default:
            break;
    }
     
     colorViewController.view.backgroundColor = bgColor;
     // Pass the selected object to the new view controller.
     [self.navigationController pushViewController:colorViewController animated:YES];
     
}

In this method, we’re instantiating colorViewController as an instance of ColorViewController. We then switch on the indexPath.row value, setting a UIColor object (bgColor) to the appropriate color. After this, we set the colorViewController’s view’s backgroundColor property to bgColor, and then push colorViewController onto the navigation controller’s stack using animation.

Run the application, and select a color from the initial table view. Notice that the navigation controller automatically places a back button in the colorViewController’s view when it is pushed, so the user can easily return to the table view.


The Table View. About to select “green” from the list…


colorViewController’s view is shown. We can return to the table view by tapping the “back” button.

Leave a Reply

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