Creating the project
Create a new project with the “View-based Application” template and call it customTableCell.
Setting up the view controller
Open customTableCellViewController.h and add two IB outlets which we will use to reference to the custom UITableViewCell objects which we will create later. Also, we are going to be using this as a table view delegate and data source so we should state that this class will conform to these protocols. Your customTableCellViewController.h should look like this after editing:
#import
@interface customTableCellViewController : UIViewController <UITableViewDataSource, UITableViewDelegate> {
IBOutlet UITableViewCell *cellOne;
IBOutlet UITableViewCell *cellTwo;
}
@property (nonatomic, retain) IBOutlet UITableViewCell *cellOne;
@property (nonatomic, retain) IBOutlet UITableViewCell *cellTwo;
@end
Adding the items in Interface Builder
Open customTableCellViewController.xib in IB and drop in a Table View (not a Table View Controller), making it fill the view.
Set the the table view properties to Style -> Grouped.
Link the delegate and dataSource outlets of the table view to “File’s Owner” as illustrated by this screenshot:

Add two Table View Cell items in IB to your customTableCellViewController.xib file. Then, open each table view cell item and drop something different onto each one of them so you will tell them apart.
Now we need to link these table view cells to the IB outlets we created earlier. To do this, right click on “File’s Owner” and link cellOne and cellTwo outlets to the table view cells you have just created. You should then have something which looks like this:

Save and close customTableCellViewController.xib.
Controller Code
Open customTableViewController.m
We will need to implement three functions, namely tableView:cellForRowAtIndexPath:, numberOfSectionsInTableView: and tableView:numberOfRowsInSection: which are the usual data source protocol functions which we need to implement. The three functions are outlined below.
tableView:cellForRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if([indexPath row] == 0) return cellOne;
if([indexPath row] == 1) return cellTwo;
return nil;
}
numberOfSectionsInTableView:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
tableView:numberOfRowsInSection:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 2;
}
These functions tell the table view to display 1 section, with 2 cells and when the table view asks for each cell, the custom UITableViewCell objects are returned.
And that’s it!
If you now build and run the application then you will notice that your custom cells are being shown – brilliant! Now you can do something fun with the custom cells! For instance you could put a text box or a slider in it and then bind actions of it to a function in your view controller to act upon the user’s input.
Go play!

Great tutorial! First one that I’ve seen that actually shows how to add custom table cells using IB and not entirely programmatically. Keep up the good work.
Thank you for your kind words Emil! I’ll certainly try to keep releasing tutorials – I’ve been doing them when I come across something which I’ve found hard to find information about on the internet / books.
Interestingly, the UITableViewCell thing has been approached by so many people in so many different ways, and there’s no true right or wrong way really.
Anyway, glad you liked the tutorial!
This can’t be right. ???
tableView:cellForRowAtIndexPath: returns a new UITableViewCell for each row. In your tutorial, it is returning the same object repeatedly!
For example, consider the conventional code:
if ((cell = [tableView dequeueReusableCellWithIdentifier:item_type]) == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:item_type] autorelease]; …
So, shouldn’t it be something like:
if ((cell = [tableView dequeueReusableCellWithIdentifier:item_type]) == nil) {
cell = [[cellOne copy] autorelease];…
?
Hi David,
What you say is sort of true, but in my example, there are only ever 2 rows. Therefore cellForRowAtIndexPath is returning a certain cell for row 0 (1st row) and a certain cell for row 1 (2nd row). This enables me to create the cell in IB and link it with outlets like I have shown.
Your method would be a good addition to be able to do the case where you have a generic cell which you want to use more than once in the same table, but want to use IB to create the cell and have it in the same XIB as the rest of the interface.
Matt
Hello,
Great tutorial Matt! A quick question: If you want to make your cells higher than the standard cells, how do you make sure that they are working properly? What I mean is that when making your custom cells higher, they are cut off sort of as they don’t fit in a standard cell (if this is clear at all).
Keep up the great work!
BN
Hello!
Yes you can do that with the heightForRowAtIndexpath function. Take a look at the documentation for the table view data source protocol and you should be able to find that function. You can just return a different height for each of your cells. Then you can make those cells the correct height in IB and you’re away. If you set things correctly in IB with regard to auto-resizing options then you’d even be able to have variable sized cells if you wanted.
Hope that helps!
Cell height related
It’s actually in the delegate not data source, here’s the link:
http://developer.apple.com/iphone/library/documentation/UIKit/Reference/UITableViewDelegate_Protocol/Reference/Reference.html#//apple_ref/occ/intfm/UITableViewDelegate/tableView:heightForRowAtIndexPath:
I started writing a tutorial about this a few days ago and finished it a few minutes ago, so if you want to see an alternative way of doing this check out my blog and feel free to comment!
http://humblecoder.blogspot.com/2009/05/iphone-tutorial-creating-table-cells-in.html
It’s not as professional looking as Matt’s, but hopefully as informative.
Nice little tutorial there Henrik! I like the idea you’ve done there, slightly different way of doing it to me. I’ve actually developed another method for doing custom cells as well but I really hope Apple decide to make it easier somehow because the difficulty is that you can’t have a NIB which is purely a view, which is just annoying…
Good Tutorial…I want to have a two cell in a row,as in contacts we have “text message” and “add to favourites” in a single row how to do that…. can anyone help me?
> Also, we are going to be using this as a table view delegate and
> data source so we should state that this class will conform to these
> protocols
You *SHOULD*… but you didn’t.
> Add two Table View Cell items in IB to your
> customTableCellViewController.xib file.
Where do you drop them in? Into the rows in the tableView?
> Then, open each table view cell item and drop something
How do you “open” a cell up?
*PLEASE* alway show a screen-shot of the final, completed screen.
Just “wishing” that your screen looks like my screen… is useless.
> You *SHOULD*… but you didn’t.
Apologies, that was Wordpress taking away the < , > thinking that it was an HTML tag. Rectified now.
> Where do you drop them in? Into the rows in the tableView?
You drop them into the XIB itself at the same level as the main UIView in there, as per the 2nd screenshot.
> How do you “open” a cell up?
Double click on it.
> *PLEASE* alway show a screen-shot of the final, completed screen.
> Just “wishing” that your screen looks like my screen… is useless.
Good idea.
This was just a very quick tutorial – it’s not part of the remit of this site that I provide “good” tutorials, I just try to help out others with what I’ve found out myself. Apologies if the tutorial wasn’t to the standard you’d hoped.
I think you should add the case where you are creating more than two as this is a typical requirement of cell subclassing
Hi,
this is a very simple to understand tutorial. It was really helpful.
Thank you for that
regards
René
Amazing! After 5 hours of searching, a simple tutorial for custom cells in IB! Thanks!
This is a very simple and easy tutorial but for some reason my UITableViewCell objects are always nil so the program crashes. It appears as if interface builder is not linking them to the IBOutlets. Although, if I click the file’s owner in interface builder it shows all cells are properly linked.
Any suggestions?
Thanks for this great tutorial. It saves me time on the table view that I would like to create.
For table view with 2 sections with 1 row on each section, the following codes can be used.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *tvcSection = nil;
int iSection = (int)[indexPath section];
switch (iSection) {
case 0: tvcSection = cellOne;
break;
case 1: tvcSection = cellTwo;
break;
}
return tvcSection;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 2;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 1;
}
Hi Matt,
awesome! Thx for the straightforward tutorial, it saved me a lot of time.
I came across one problem: In my app, I need to dynamically show and hide 5 cells I created as exposed. That’s no problem using the “hidden” property of the cells, however, I need this behaviour animated. So what I’ve tried to do first of all instead of hiding is deleting the cells like this:
[fooTable deleteRowsAtIndexPaths:[NSArray arrayWithObject:fooIndexPath]] withRowAnimation:UITableViewRowAnimationTop];
This results in the following exception:
‘Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (3) must be equal to the number of rows contained in that section before the update (5), plus or minus the number of rows inserted or deleted from that section (0 inserted, 1 deleted).’
I’m not sure if this has something to do with the dataSource which should probably be updated as well, but… how?
Thanks for any suggestions!
cheers,
Sascha