Sunday, July 1, 2012

objective c UITableViewController


UITableViewController

 

UITableViewController is a convenience class used to manage a table view. It does have some limitations, but as a beginner, it is a great place to start. Moreover, it aids in understanding some of the commonly used classes in iOS such as delegates and datasources.

Anatomy of a UITableViewController

As mentioned earlier the UITableViewController is a convenience class, which means that it is made of existing components and neatly packaged for ease of use as depicted in the image below.
Anatomy of a UITableViewController

Creating the UITableViewController

Open up Xcode 4 and create a new Project (⇧⌘N)
Select Navigation-Based Application
Navigation-Based Application
Give your Product a name (we will display a list of Books, so you can just call it Books)
Product name
Once the project has been created, click on your RootViewController.h in the navigation pane. Notice that all it does is inherit the UITableViewController because that’s all you need for now.
RootViewController.h
Next click on RootViewController.m and notice that you have method stubs for UITableViewDataSource and UITableViewDelegate. The methods numberOfSectionsInTableView and numberOfRowsInSection determine the number of sections and rows in the table view. By default numberOfSectionsInTableView returns 1 because that is minimum number of sections allowed.
RootViewController.m

Populating the UITableViewController

Configuring the model

We will display a simple list of books in the table view for that we need to build an array. Declare a property called booksArray in the interface RootViewController.h which will serve as the underlying model for our table view.
1
2
3
4
5
6
7
#import <UIKit/UIKit.h> 
 
@interface RootViewController : UITableViewController 
 
@property (nonatomic, retain) NSArray *booksArray; 
 
@end
Adding a property requires us to setup getter and setter methods for it. That is easily done by calling @synthesize within the implementation in RootViewController.m which automatically creates the getter and setter methods.
1
2
3
#import "RootViewController.h" 
@implementation RootViewController 
@synthesize booksArray;
We need to initialize the array and can do it in the viewDidLoad method because it is called just once, it is similar to calling window.onload or document.ready when programming for the web. In the code below we are calling a class method arrayWithObjects on NSArray as we pass it a comma-separated list of strings terminated by a nil which returns an array of NSString objects.
1



- (void)viewDidLoad { 
    [super viewDidLoad]; 
    self.booksArray = 
[NSArray arrayWithObjects: @"Brave new world",
@"Call of the Wild",@"Catch-22",@"Atlas Shrugged", 
@"The Great Gatsby",@"The Art of War",@"The Catcher in the Rye", 
@"The Picture of Dorian Gray",@"The Grapes of Wrath", @"The Metamorphosis",nil]; 
}

Configuring the datasource

Now that we have the books array we can determine the number of rows in our table view. For that we need to return the size of our books array from the method numberOfRowsInSection

(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:  
(NSInteger)section { 
    return self.booksArray.count; 
}
The table view is made up of UITableViewCells and the datasource is responsible for creating and returning instances of these cells.
1
2
3
4
5
6
7
8
9
10
11
12
13
// 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.booksArray objectAtIndex:indexPath.row]; 
    return cell; 
}
Going through each line of code above:
1
    static NSString *CellIdentifier = @"Cell";
A NSString CellIdentifier is defined as static because this method is called several times. Static will not recreate an instance if it already exists and keeps its value despite it being local in scope.
1
    UITableViewCell *cell =
  [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
Here we are sending a message to the tableView instance asking if there is a UITableViewCell object available with the CellIdentifier declared previously. For performance reasons, a table view data source generally reuses UITableViewCell objects. The table view maintains a queue of cell objects that are marked for reuse. For example, if you were displaying a list that contained a 1000 rows it would be highly inefficient to create 1000 table view cells, whereas a lot of more effective to create the few currently in view. When the user scrolls the table view just reuses the cells that are no longer in view with the new data.
1
2
3
    if (cell == nil) { 
        cell = 
[[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault 
reuseIdentifier:CellIdentifier] autorelease]; 
    }
If there is no cell object available for reuse then create a new one. When creating a new UITableViewCell we pass the CellIdentifier so that the data source can later access reusable cell objects in the queue by invoking the dequeueReusableCellWithIdentifier: method.
1
    cell.textLabel.text = [self.booksArray objectAtIndex:indexPath.row];
Each UITableViewCell has a UILabel called textLabel to which you can assign a NSString. We get the NSString from the booksArray at the row that corresponds to the cell being displayed based on indexPath object passed to this method. The class IndexPath contains two main properties: Section and Row. Since we have only one section we are just concerned with the row.

Done!

Congratulations! You are done creating your first table view! Run your app (⌘R) in the simulator to see the results
Table view running in iPhone Simulator

 

No comments: