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.
Creating the UITableViewController
Open up Xcode 4 and create a new Project (⇧⌘N)
Select Navigation-Based Application
Give your Product a name (we will display a list of Books, so you can just call it Books)
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.
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.
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
No comments:
Post a Comment