Customize Table View Cells for UITableView


In this tutorial, we’ll continue to work on the app and make it even better:
  • Display different images for different rows – lastly, we display the same thumbnail for all rows. Wouldn’t be better to show individual image for each recipe?
  • Customize the table view cell – instead of using the default style of table view cell, we’ll take a look how to build our own.

Display Different Thumbnails

Before we move on to change the code, let’s revisit the code for displaying thumbnail in table row.
SimpleTable Image Code
Lastly, we’ve added a line of code to instruct UITableView to display “creme_brelee.jpg” in each row. Obviously, in order to show different images, we need to alter this line of code. As explained before, the “cellForRowAtIndexPath” method is called by iOS automatically each time before a table row is displayed.
1
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
If you look into the method parameter, it passes the “indexPath” when invoked. The indexPathparameter contains the row number (as well as the section number) of the table row. You can simply use “indexPath.row” property to find out which row it currently points to. Like an array, the count of table row starts from zero. In other words, “indexPath.row” property returns 0 for the first row of table.
So to display different thumbnails, we’ll add a new array (i.e. thumbnails) that stores the file name of thumbnails:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@implementation SimpleTableViewController
{
    NSArray *tableData;
    NSArray *thumbnails;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Initialize table data
    tableData = [NSArray arrayWithObjects:@"Egg Benedict"@"Mushroom Risotto"@"Full Breakfast"@"Hamburger"@"Ham and Egg Sandwich"@"Creme Brelee"@"White Chocolate Donut"@"Starbucks Coffee"@"Vegetable Curry"@"Instant Noodle with Egg"@"Noodle with BBQ Pork"@"Japanese Noodle with Pork"@"Green Tea"@"Thai Shrimp Cake"@"Angry Birds Cake"@"Ham and Cheese Panini"nil];
    
    // Initialize thumbnails
    thumbnails = [NSArray arrayWithObjects:@"egg_benedict.jpg"@"mushroom_risotto.jpg"@"full_breakfast.jpg"@"hamburger.jpg"@"ham_and_egg_sandwich.jpg"@"creme_brelee.jpg"@"white_chocolate_donut.jpg"@"starbucks_coffee.jpg"@"vegetable_curry.jpg"@"instant_noodle_with_egg.jpg"@"noodle_with_bbq_pork.jpg"@"japanese_noodle_with_pork.jpg"@"green_tea.jpg"@"thai_shrimp_cake.jpg"@"angry_birds_cake.jpg"@"ham_and_cheese_panini.jpg"nil];
}
As you can see from the above code, we initialize the thumbnails array with a list of image file names. The order of images are aligned with that of the “tableData”.
For your convenience, you can download this image pack and add them into your project. Make sure “Copy items into destination group’s folder” is enabled.
SimpleTable Add File
After adding the image files, you should find them in the Project Navigator like the screen shown below:
SimpleTable Project Navigator Image
Lastly, change the line of code in “cellForRowAtIndexPath” method to:
1
cell.imageView.image = [UIImage imageNamed:[thumbnails objectAtIndex:indexPath.row]];

What’s [thumbnails objectAtIndex:indexPath.row]?

The line of code retrieves the name of images for the specific row. Say, for the first row, indexPath.row property returns 0 and we picks the first image (i.e. egg_benedict.jpg) from the thumbnails array using the “objectAtIndex” method.
After saving all the changes, try to run your app again. It should now display different thumbnails for the table rows:
SimpleTable App With Different Thumbnails

Customize Table View Cell

Does the app look better? We’re going to make it even better by customizing the table cell. So far we utilize the default style of table view cell. The location and size of the thumbnail are fixed. What if you want to make the thumbnail bigger and show the preparation time for each recipe just like the below screen?
SimpleTableView Custom Cell
Custom Table View Cell with Different Style

Designing the Cell

In this case, you have to create and design your own table cell. Go back to Xcode. In Project Navigator, right click “SimpleTable” folder and select “New File…”.
As we’re going to design our own table cell, we have to create a new Interface Builder file for the cell. For this case, we just need to start with an “Empty” user interface. Click “Next” to continue.
New Empty Interface Builder File
Select an Empty Interface Builder Document
When prompt to choose the device family, select “iPhone” and click “Next” to continue. Save the file as “SimpleTableCell”.
SimpleTableCell Interface Builder Document
Once the file is created, you should find it in Project Navigator. Select “SimpleTableCell.xib” to switch to Interface Builder. We’re going to design the look and feel of the custom table cell.
In the Object Library, select “Table View Cell” and drag it to the design area of the Interface Builder.
SimpleTable Drag TableViewCell
In order to accommodate a larger thumbnail, we have to change the height of the cell. Just hold the lower/upper side of the cell and scale the height to 78.
Table View Cell Change Height
Alternatively, you can also use the “Size Inspector” to change the height.
Table View Cell Size Inspector
Size Inspector for Table View Cell
Next, select the “Attributes Inspector” in the upper part of the Utility area and set the “Identifier” of the custom cell to “SimpleTableCell”. This identifier will be used later in your code.
SimpleTable Cell Identifier
After configuring the table cell view, we’ll put other elements inside it. Select “Image View” and drag it into the Table View Cell.
SimpleTableCell Drag ImageView
This image view will be used for displaying the thumbnail. You can resize it to make it fit the cell. For your reference, I set both the height and width to 69 pixels.
Next, we’ll add three labels: Name, Prep Time and Time. The “Name” label will be used to display the name of recipe. The “Prep Time” is a static label that only displays the text of “Prep Time:”. Lastly, the “Time” label is a dynamic label that is used to show the actual preparation time for the specific recipe.
To add a label, select “Label” in Object library and drag it to cell. You can double click the label to change its name.
Table View Cell Change Label Name
You may notice your font size and style are different from the one shown above. To change the font style, simply select the Label and select the “Attribute Inspector”. From here, you can alter the setting of “Font” and minimum font size. You can also change the text color and alignment through the inspector.
Custom Table Cell Attributes
Your final design should look similar to this:
Final Design Table View Cell

Creating a Class for the Custom Cell

So far, we’ve designed the table cell. But how can we change the label values of the custom cell? We’re going to create a new class for the custom table view cell. This class represents the underlying data model of the custom cell.
Just like before, right click the “SimpleTable” folder in Project Navigator and select “New File…”.
New File Template Dialog
Pick a Template for the New File
Right after selecting the option, Xcode prompts you to select a template. As we’re going to create a new class for the custom table view cell, select “Objective-C class” under “Cocoa Touch” and click “Next”.
SimpleTable New File
Create New File for Your Project
Fill in “SimpleTableCell” for the class name and select “UITableViewCell” for the “Subclass of” option.
SimpleTable Subclass UITableViewCell
Click “Next”, save the file in the SimpleTable project folder and click “Create” to continue. Xcode should create two files named “SimpleTableCell.h” and “SimpleTableCell.m” in the Project Navigator.
As mentioned before, the SimpleTableCell class serves as the data model of custom cell. In the cell, we have three values that are changeable: the thumbnail image view, the name label and the time label. In the class, we’ll add three properties to represent these dynamic values.
Open “SimpleTableCell.h” and add the following properties before the “@end” line:
1
2
3
@property (nonatomic, weak) IBOutlet UILabel *nameLabel;
@property (nonatomic, weak) IBOutlet UILabel *prepTimeLabel;
@property (nonatomic, weak) IBOutlet UIImageView *thumbnailImageView;

Property and Outlet

The above lines of code defines three instance variables that later to be associated with the table cell view in Interface Builder. The keyword “@property” is used to declare a property within a class in the following form:
@property (attributes) type name;
Referring to the lines of code above, weak and nonatomic are the attributes of the property. UILabel and UIImageView are the types, while the “nameLabel”, “prepTimeLabel” and “thumbnailImageView” are the names.
So what’s IBOutlet? You can think of IBOutlet as an indicator. To associate the instances variables with the elements in the Table View Cell (i.e. SimpleTableCell.xib), we use the keyword “IBOutlet” to let Interface Builder know that they’re allowed to make connection. Later, you’ll see how to make a connection between these outlets and the objects in Interface Builder.
Now, open “SimpleTableCell.m” and add the following code right below “@implementation SimpleTableCell”:
1
2
3
@synthesize nameLabel = _nameLabel;
@synthesize prepTimeLabel = _prepTimeLabel;
@synthesize thumbnailImageView = _thumbnailImageView;

@synthesize Directive

The “@synthesize” keyword tells compiler to automatically generate code for accessing the properties we declared earlier. If you forget to include this directive, Xcode will complain like below:
Xcode Missing Synthesize

Making the Connections

Save the changes and select “SimpleTableCell.xib” to go back to Interface Builder. Now we’ll make connections between the properties of the class and the Label/ImageView created in the Interface.
First, select the cell and change the class to “SimpleTableCell” in “Identity Inspector”. This associates the cell view with our custom class created earlier.
Now, we’ll establish the connections with the properties. Right click the “SimpleTableCell” under “Objects” to display the “Outlets” inspector. Click and hold the circle next to “nameLabel”, and drag it to the “Label – Name” object. Xcode automatically establishes the connection.
Simple Table Cell Label Connection
Repeat the above procedures for “prepTimeLabel” and “thumbnailImageView”:
  • Connect “prepTimeLabel” with “Label – Time” object
  • Connect “thumbnailImageView” with “ImageView” object
After you made all the connections, it should look like this:
Simple Table Cell Connections

Updating SimpleTableViewController

We have completed the design and coding for the custom table cell. Finally we come to the last part of the change – to make use of the custom cell in the SimpleTableViewController.
Let’s revisit the code in “SimpleTableView.m” that currently used to create table row:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *simpleTableIdentifier = @"SimpleTableItem";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];

    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
    }

    cell.textLabel.text = [tableData objectAtIndex:indexPath.row];
    cell.imageView.image = [UIImage imageNamed:[thumbnails objectAtIndex:indexPath.row]];

    return cell;
}
We use the default table view cell (i.e. UITableViewCell) for showing the table items. In order to use our custom table cell, we have to alter this part of code in “SimpleTableView.m” to the following:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *simpleTableIdentifier = @"SimpleTableCell";

    SimpleTableCell *cell = (SimpleTableCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
    if (cell == nil) 
    {
        NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"SimpleTableCell" owner:self options:nil];
        cell = [nib objectAtIndex:0];
    } 
    
    cell.nameLabel.text = [tableData objectAtIndex:indexPath.row];
    cell.thumbnailImageView.image = [UIImage imageNamed:[thumbnails objectAtIndex:indexPath.row]];
    cell.prepTimeLabel.text = [prepTime objectAtIndex:indexPath.row];
    
    return cell;
}
However, as soon as you update the code, Xcode detects there are some errors as indicated in the source code editor.
Xcode Source Editor Error
Source Code Error Indicated by Xcode
What’s the problem? The code we’ve just changed tells “SimpleTableViewController” to use “SimpleTableCell” class as the table cell. However, “SimpleTableViewController” doesn’t have any idea about it. That’s why Xcode displays errors.
As explained in the first tutorial, a header file declares the interface of a class. For “SimpleTableViewController” to get to know “SimpleTableCell”, we have to import the “SimpleTableCell.h” in the “SimpleTableViewController.m”.
SimpleTableView Controller Import
Import SimpleTableCell.h
By importing “SimpleTableCell.h”, the “SimpleTableViewController” knows what it is and can make use of it.
Lastly, as the height of table cell is changed to 78, add the below code above “@end”.
1
2
3
4
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return 78;
}
Now, hit the “Run” button and your SimpleTable app should look like below:
SimpleTable App with Custom Cell
Customize Table View Cells for UITableView Customize Table View Cells for UITableView Reviewed by Unknown on 17:49 Rating: 5

No hay comentarios:

Con la tecnología de Blogger.