tote tote - 11 months ago 45
Objective-C Question

UITableView with fixed section headers

I'm reading that the default behaviour of UITableView is to pin section header rows to the top of the table as you scroll through the sections until the next section pushes the previos section row out of view.

I have a UITableView inside a UIViewController and this does not seem to be the case.

Is that just the defualt behaviour for UITableViewController?

Here's some simplified code based on what I have.
I'll show the UIController interface and each table view method I've implemented to create the table view.
I have a helper data source class that helps me index my objects for use with the table.

@interface MyUIViewController ()<UITableViewDelegate, UITableViewDataSource>
@property (nonatomic, readonly) UITableView *myTableView;
@property (nonatomic, readonly) MyCustomHelperDataSource *helperDataSource;

//when section data is set, get details for each section and reload table on success
- (void)setSectionData:(NSArray *)sections {
super.sectionData = sections; //this array drives the sections

//get additional data for section details
[[RestKitService sharedClient] getSectionDetailsForSection:someId
success:^(RKObjectRequestOperation *operation, RKMappingResult *details) {
NSLog(@"Got section details data");
_helperDataSource = [[MyCustomHelperDataSource alloc] initWithSections:sections andDetails:details.array];
[myTableView reloadData];
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
NSLog(@"Failed getting section details");

#pragma mark <UITableViewDataSource, UITableViewDelegate>

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
if (!_helperDataSource) return 0;
return [_helperDataSource countSectionsWithDetails]; //number of section that have details rows, ignore any empty sections

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
//get the section object for the current section int
SectionObject *section = [_helperDataSource sectionObjectForSection:section];
//return the number of details rows for the section object at this section
return [_helperDataSource countOfSectionDetails:section.sectionId];

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

UITableViewCell * cell;

NSString *CellIdentifier = @"SectionDetailCell";

cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
cell.textLabel.font = [UIFont systemFontOfSize:12.0f];

//get the detail object for this section
SectionObject *section = [_helperDataSource sectionObjectForSection:indexPath.section];

NSArray* detailsForSection = [_helperDataSource detailsForSection:section.sectionId] ;
SectionDetail *sd = (SectionDetail*)[detailsForSection objectAtIndex:indexPath.row];

cell.textLabel.text = sd.displayText;
cell.detailTextLabel.text = sd.subText;
cell.detailTextLabel.textColor = [UIColor blueTextColor];

return cell;

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 50.0f;

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
return 30.0f;

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger) section {
//get the section object for the current section
SectionObject *section = [_helperDataSource sectionObjectForSection:section];

NSString *title = @"%@ (%d)";

return [NSString stringWithFormat:title,, [_helperDataSource countOfSectionDetails:section.sectionId]];

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
UIView *header = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 260, 0)];
header.autoresizingMask = UIViewAutoresizingFlexibleWidth;

header.backgroundColor = [UIColor darkBackgroundColor];

SSLabel *label = [[SSLabel alloc] initWithFrame:CGRectMake(3, 3, 260, 24)];
label.font = [UIFont boldSystemFontOfSize:10.0f];
label.verticalTextAlignment = SSLabelVerticalTextAlignmentMiddle;
label.backgroundColor = [UIColor clearColor];
label.text = [self tableView:tableView titleForHeaderInSection:section];
label.textColor = [UIColor whiteColor];
label.shadowColor = [UIColor darkGrayColor];
label.shadowOffset = CGSizeMake(1.0, 1.0);
[header addSubview:label];

return header;


That behavior is only common when the UITableViewStyle property of the table is set to UITableViewStylePlain. If you have it set to UITableViewStyleGrouped, the headers will scroll up with the cells.