ylliX - Online Advertising Network

Tutorial: Custom UITable section header using Interface Builder

I saw a lot of tutorials about custom header/footer, or even custom section header, but they were creating controls programatically, in this tutorial I want to show how easy is to use Interface Builder to achive same result.

So start with creating new XCode project:

Choose “Single View Application”:
Zrzut ekranu 2015-01-11 o 10.09.37

Enter name whatever you want:
Zrzut ekranu 2015-01-11 o 10.10.26

And we can start finally. So using Interface Builder create UITable and two custom cells, one for table row, one for section header, also add one UILabel in each (so we can display something):

Zrzut ekranu 2015-01-11 o 10.59.04

If your view looks like above – you’re on good way. Now we need to give our cells a reusable identifier – to get them later:

Zrzut ekranu 2015-01-11 o 10.20.15

As you can see, my row cell has identifier “tableitem” and my header cell has “headeritem”. So let’s connect assets to header file ViewController.h:

@interface ViewController : UIViewController
    __weak IBOutlet UITableView *table;


and after right-click on table you should have:

Zrzut ekranu 2015-01-11 o 10.23.41

Now we need to add UITableViewDataSource and UITableViewDelegate and place for your data, still in ViewController.h:

@interface ViewController : UIViewController <UITableViewDataSource,UITableViewDelegate>
    __weak IBOutlet UITableView *table;
    NSMutableArray* tableData;


Then open ViewController.m and add some code to make it look like this:

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    tableData = [[NSMutableArray alloc] init];
    [tableData addObject:@[@{@"key": @"1", @"label": @"item 1.1"}, @{@"key": @"1", @"label": @"item 1.2"}, @{@"key": @"3", @"label": @"item 1.3"}] ];
    [tableData addObject:@[@{@"key": @"1", @"label": @"item 2.1"}, @{@"key": @"2", @"label": @"item 2.2"}, @{@"key": @"3", @"label": @"item 2.3"}, @{@"key": @"4", @"label": @"item 2.4"}] ];
    table.delegate = self;
    table.dataSource = self;
    [table reloadData];

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
    return [tableData count];

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    return [[tableData objectAtIndex:section] count];

-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
    return 90.0;


As you can see we don’t have cellForRowAtIndexPath and viewForHeaderInSection implemented yet, its only some basic code. There is a strange number in heightForHeaderInSection function, it should be your section header height you set in Interface Builder. If value will be different, your header will have too much space or view will be cut.

Now we need to extend UITableViewCell twice – first for table row, second for section header. So add new file:

Zrzut ekranu 2015-01-11 o 10.31.41

and second one:

Zrzut ekranu 2015-01-11 o 10.32.32

So now you file browser will look like this:

Zrzut ekranu 2015-01-11 o 10.33.21

Now connect you labels to your new classes, you RowCell.h should look like this:

@interface RowCell : UITableViewCell

@property (weak, nonatomic) IBOutlet UILabel *lblRowData;


And SectionHeaderCell.h like this:

@interface SectionHeaderCell : UITableViewCell

@property (weak, nonatomic) IBOutlet UILabel *lblSectionData;


Next step is connection from Interface Builder to you vars, but first you need to assign your classes to proper cells, for table row:

Zrzut ekranu 2015-01-11 o 10.48.10

and for section header:

Zrzut ekranu 2015-01-11 o 10.48.44

So now your row cell should be connected to its var:

Zrzut ekranu 2015-01-11 o 10.50.34

So should be section header cell:
Zrzut ekranu 2015-01-11 o 10.51.27Now we can add required imports to ViewController.m:

#import "RowCell.h"
#import "SectionHeaderCell.h"

And add UITable delegate methods:

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
    SectionHeaderCell *cell = (SectionHeaderCell*)[tableView dequeueReusableCellWithIdentifier:@"headeritem"];
    cell.lblSectionData.text = [NSString stringWithFormat:@"Header: %i", section];
    return cell.contentView;

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    RowCell *cell = (RowCell*)[tableView dequeueReusableCellWithIdentifier:@"tableitem"];
    cell.lblRowData.text = [NSString stringWithFormat:@"%i.%i", indexPath.section, indexPath.row];
    return cell;

Some notes here, in cellForRowAtIndexPath as usual you get your cell via dequeueReusableCellWithIdentifier then you need to cast returned object to your RowCell class so instead of using viewWithTag method, you can just use cell.yourAsset. Very similar stuff goes in viewForHeaderInSection but, since this method has to return UIView, not UITableViewCell, we’re returning contentView property of UITableViewCell. Now compile and run your project and you should see:

Zrzut ekranu 2015-01-11 o 10.59.57

Feel free to play with interface assets to achieve look you want. If you want, you can grab whole project on GitHub here.

Leave a Reply