IMPORTANT:
The following tutorial has been deprecated and should no longer be used for any purposes. To learn more on how to use the UITableView click here

Welcome to the fourth part of UITableView tutorial where I should you how to create multiple columns in a UITableViewCell

Welcome to the 4th part of the Table View Tutorial. In this tutorial, we will learn how to create a UITableViewCell with multiple columns. In these columns, we can place images and text.

It is recommended that you read the 1st part of the Table View Tutorial here, before reading this one. The source code for this tutorial has been copied from the Part 3 of the Table View Tutorial.

This is how the application will look like when we are done

We are going to add two columns to the UITableViewCell, where one of the column will show the index number and the other column will show some custom text as seen in the image above. To do this we have to customize the UITableViewCell object which is returned in the cellForRowAtIndexPath method.

We can do this in two ways

  1. Inherit from UITableViewCell
  2. Create a simple method which will customize the UITableViewCell.

If this were to be a real world application, I would advice to inherit from UITableViewCell, but to learn how to create multiple columns, we will use a simple method.

Before we dive into the details, we first need to define some macros which will be the offsets, widths and heights of the objects and the UITableViewCell itself. Think of macros for now as a constant which has a proper name which will be substituted with the original value at runtime.

FileName: TableViewController.m – Declared before the implementation begins
#define ROW_HEIGHT 40
#define CELL_WIDTH 320.0
#define LABEL_HEIGHT 20

//Lets define the dimensions of the two columns
//Set the column offset and the width.
#define NUMBER_OFFSET 10.0
#define NUMBER_WIDTH 50.0
#define NUMBER_TAG 1

#define TEXT_OFFSET 60.0
#define TEXT_WIDTH 270.0
#define TEXT_TAG 2

Start by declaring a method called reuseTableViewCellWithIdentifier in TableViewController.h file. This file is created in the Part 1 of this tutorial series. reuseTableViewCellWithIdentifier takes an NSString variable and returns UITableViewCell.

This is how the header file will look like

FileName: TableViewController.h#import <UIKit/UIKit.h>

@class SubViewController;

@interface TableViewController : UIViewController <UITableViewDataSource, UITableViewDelegate> {

IBOutlet UITableView *tblView;
SubViewController *svController;

}

@property (nonatomic, retain) UITableView *tblView;
@property (nonatomic, retain) SubViewController *svController;

-(UITableViewCell *)reuseTableViewCellWithIdentifier:(NSString *)identifier;

@end

We then implement the method in TableViewController.m file and this is the source code for the method

FileName: TableViewController.m
-(UITableViewCell *)reuseTableViewCellWithIdentifier:(NSString *)identifier {

//Rectangle which will be used to create labels and table view cell.
CGRect cellRectangle;

//Returns a rectangle with the coordinates and dimensions.
cellRectangle = CGRectMake(0.0, 0.0, CELL_WIDTH, ROW_HEIGHT);

//Initialize a UITableViewCell with the rectangle we created.
UITableViewCell *cell = [[[UITableViewCell alloc] initWithFrame:cellRectangle reuseIdentifier:identifier] autorelease];

//Now we have to create the two labels.
UILabel *label;

//Create a rectangle container for the number text.
cellRectangle = CGRectMake(NUMBER_OFFSET, (ROW_HEIGHT – LABEL_HEIGHT) / 2.0, NUMBER_WIDTH, LABEL_HEIGHT);

//Initialize the label with the rectangle.
label = [[UILabel alloc] initWithFrame:cellRectangle];

//Mark the label with a tag
label.tag = NUMBER_TAG;

//Add the label as a sub view to the cell.
[cell.contentView addSubview:label];
[label release];

//Create a rectangle container for the custom text.
cellRectangle = CGRectMake(TEXT_OFFSET, (ROW_HEIGHT – LABEL_HEIGHT) / 2.0, TEXT_WIDTH, LABEL_HEIGHT);

//Initialize the label with the rectangle.
label = [[UILabel alloc] initWithFrame:cellRectangle];

//Mark the label with a tag
label.tag = TEXT_TAG;

//Add the label as a sub view to the cell.
[cell.contentView addSubview:label];
[label release];

return cell;
}

We achieve the illusion of multiple columns in a UITableViewCell by adding different objects as a sub view to the UITableViewCell. These objects in the UITableViewCell are placed at different offsets and are of different widths.

We start of by declaring an object of type CGRect, which we will use to create frame rectangles and then initialize the UILabel and the UITableViewCell with it. Using a frame rectangle, we can specify the offset, width of the label on the UITableViewCell. We initialize the UITableView object with the help of the cellRectangle which is created using these coordinates and dimensions.

//Rectangle which will be used to create labels and table view cell.
CGRect cellRectangle;

//Returns a rectangle with the coordinates and dimensions.
cellRectangle = CGRectMake(0.0, 0.0, CELL_WIDTH, ROW_HEIGHT);

//Initialize a UITableViewCell with the rectangle we created.
UITableViewCell *cell = [[[UITableViewCell alloc] initWithFrame:cellRectangle reuseIdentifier:identifier] autorelease];

CGRectMake takes four parameters, the first two being the x, y position and the last two being the width, height of the object. Here the UITableViewCell is created the same way as earlier but instead of passing CGRectZero we are passing a rectangle defined by us.

UITableViewCell *cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:identifier] autorelease];

UITableViewCell *cell = [[[UITableViewCell alloc] initWithFrame:cellRectangle reuseIdentifier:identifier] autorelease];

We then create a Label and initialize with offset 10,(10 = (40-20)/2). This way the label will be placed 10 pixels away (pixels is probably a wrong word here but I thought it will be easier to understand) and the text will be placed 10 pixels top from the bottom. The other two parameters specify what will be the width and the height of the control. Then we initialize a label using the frame rectangle we just created.

//Now we have to create the two labels.
UILabel *label;

//Create a rectangle container for the number text.
cellRectangle = CGRectMake(NUMBER_OFFSET, (ROW_HEIGHT – LABEL_HEIGHT) / 2.0, NUMBER_WIDTH, LABEL_HEIGHT);

//Initialize the label with the rectangle.
label = [[UILabel alloc] initWithFrame:cellRectangle];

we mark the label using the tag property, so it can be retrieved later using viewWithTag method. The label is then added as a sub view to the contentView property of UITableViewCell object. The memory of the label is released, so it can be reused again.

//Mark the label with a tag
label.tag = NUMBER_TAG;

//Add the label as a sub view to the cell.
[cell.contentView addSubview:label];
[label release];

The same procedure is repeated again, for the second column.

Now we have to set the appropriate text in cellForRowAtIndexPath method and this is how the method will be changed

TableViewController.m
-(UITableViewCell *)tableView:(UITableView *)tblView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

static NSString *identifier = @”MyCell”;

UITableViewCell *cell = [self.tblView dequeueReusableCellWithIdentifier:identifier];
if(cell == nil)
cell = [self reuseTableViewCellWithIdentifier:identifier];

//cell.text = [[NSString alloc] initWithFormat:@”Cell : %i”, indexPath.row];

//Now instead of passing data to the text property of the cell.
//We will get the label by tag and set data to the text property of the label

UILabel *lbl = (UILabel *)[cell viewWithTag:NUMBER_TAG];
lbl.text = [NSString stringWithFormat:@"%i. ", indexPath.row + 1];

UILabel *lblText = (UILabel *)[cell viewWithTag:TEXT_TAG];
lblText.text = @”Custom Cell text”;

return cell;
}

We call the reuseTableViewCellWithIdentifier to give us a new UITableViewCell object. We then call viewWithTag method on the cell to get the right object added to the contentView of the UITableViewCell. viewWithTag returns id and we cast it to the object we want. In our case we cast it to UILabel.

We get the label for NUMBER_TAG and set current row index number. We add this value by 1, because the row number starts from zero. We get the UILabel by passing TEXT_TAG to viewWithTag method and set some text to the label. Now all we have to do is return the UITableViewCell object as usual.

Click on Build and Go to see the results.

You can download the source code for this project here.

Please let me know your thoughts and if you have any questions you can email me at iphonearticles [@] gmail [.] com. I will reply as I find time, usually over the weekend. You can also post your questions to the iPhone SDK Development group here.

IMPORTANT:
The following tutorial has been deprecated and should no longer be used for any purposes. To learn more on how to use the UITableView click here
 

5 Responses to Table View Tutorial – TableView Cell Columns

  1. Anonymous says:

    >Thanks for the tutorial but why is my lbl.text and lblText.text always null?

  2. Anonymous says:

    >I am not sure why but my lbl.text and lblText.text is always null…

  3. Piruz says:

    >Hi !

    Thanks for your tutos.

    I’ve a question :
    I would return from the second view to the table view. So, no problem, I made a button, and it works perfectly, but :
    I would the screen display the row with the number wich was displayed on the second view.

    Err, to be more explicit, by example, if in the TableView, I touch the row number 5 (we imagine we have 100 rows in total, ok ?), i’ll go to the second view and it will display “Select Row Number : 5″. If I touch the button I’ve created, it will go to the TableView, but the row on the top of the screen will be the row number 0 (or 1), and I would the 5.

    No problem to pass the NSInteger from the table to the second view, and I have found a method : “- (void)scrollToRowAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated;”, but I don’t see how make it usual (I only have errors when I tried to use this (dunno where I have to place this method) =/).

    Could you explain to me how could I use this method ?
    It could be great =)

    (I posted this question in the comments because I think it could be useful for the others, but don’t hesite to moderate it if it isn’t appropriate (and sorry for english errors, I’m a french who try his best =p))

    Thank you by advance !

    Piruz
    (farges_y@gmt-editions.fr)

  4. jai says:

    >Hi Ankit,

    Follow this tutorial http://www.iphonesdkarticles.com/2008/08/table-view-tutorial-tableview-cell.html. I think it will be better if you create two labels and add the labels to the content view of the cell as shown in the tutorial, this way you will be able to control the height/width of the cell.

    So one label will be used for the image and the other to display text.

    Happy Programming
    iPhoneSDKArticles

  5. ankitthakur says:

    >Thanks for such a nice tutorial.

    Sir, I am trying to display image and Text both in my UITableViewcell
    where I am able to display both, but able to make the size of cell equals to the size of the image, as image size is large enough.
    Here is my code, please check it.

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *MyIdentifier = @”MyIdentifier”;

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
    if (cell == nil) {
    cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:MyIdentifier] autorelease];
    cell.accessoryType=UITableViewCellAccessoryDetailDisclosureButton;
    }
    /**************************************************/
    NSMutableArray *array = [NSMutableArray arrayWithObjects: @"Aquarius", @"Aries", @"Cancer", @"Taurus",@"Capricorn",@"Gemini", nil];
    //index path is definately required
    int x=indexPath.row;

    NSString* imag1=[[NSBundle mainBundle] pathForResource:[array objectAtIndex:x] ofType:@”png”];
    UIImage* myImg=[[UIImage alloc] initWithContentsOfFile:imag1];
    CGRect imageRect=CGRectMake(0.0, 0.0, 100.0 , 100.0);
    cell = [[[UITableViewCell alloc] initWithFrame:imageRect reuseIdentifier:MyIdentifier] autorelease];
    cell.accessoryType=UITableViewCellAccessoryDetailDisclosureButton;
    cell.text=[array objectAtIndex:x];
    cell.image=myImg;

    /***************************************************/

    // Set up the cell
    return cell;
    }

    Please help.
    Ankit Thakur
    ankitthakur85@gmail.com