Kisel Alexander
Kisel Alexander

Reputation: 750

How to get section header from UItableView

I am trying to get section header view using this code:

[tableView headerViewForSection:indexPath.section];

but this code always returns me nil. Could you give me some examples to get section header view from table view? This is my viewForHeader implementation:

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{

  DynamicHeader *headerView = [[DynamicHeader alloc] init];
        headerView.frame = CGRectMake(0, 0, 320, 40);
        UILabel *headerLbl = [[UILabel alloc] init];
        headerLbl.frame = CGRectMake(10, 10, 300, 20);
        if(((SectionViewController *)sharedInstance.currentViewController).currentSectionType == 25)
        {
            UIImageView *imgView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"minus.png"]];
            imgView.frame = CGRectMake(285, 14.5, 16, 13);
            [headerView addSubview:imgView];
            UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:sharedInstance action:@selector(headerTap:)];
            [headerView addGestureRecognizer:recognizer];
            headerView.tableView = tableView;
            headerView.heightForRows = 95;
            headerView.isOpen = YES;
        }
 headerLbl.text = [[[[[((SectionViewController *)sharedInstance.currentViewController).responseDictionary valueForKey:DATA_PARAMETER] valueForKey:SECTION_TABLE_PARAMETER] objectAtIndex:section] valueForKey:TABLE_SECTION_HEADER] capitalizedString];
 [headerView addSubview:headerLbl];

        return headerView;

}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{

 if((DynamicHeader *)[tableView headerViewForSection:indexPath.section] != nil)
        {
            return ((DynamicHeader *)[tableView headerViewForSection:indexPath.section]).heightForRows;
        }
        else
        {
            return 95;
        }

}


- (void)headerTap: (UITapGestureRecognizer *)recognizer
{
    DynamicHeader *view = (DynamicHeader *)[recognizer view];
    if(view.isOpen)
    {
        view.heightForRows = 0;

    }
    else
    {
        view.heightForRows = 95;
    }
    view.isOpen = !view.isOpen;

    [view.tableView beginUpdates];
    [view.tableView endUpdates];
}

Upvotes: 15

Views: 27008

Answers (6)

Dag Ågren
Dag Ågren

Reputation: 1147

Your header view must inherit from UITableViewHeaderFooterView or else this call will not work and always returns nil.

Upvotes: 2

Sean Chen
Sean Chen

Reputation: 259

Use this delegate method to access the header view:

- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section

Upvotes: 3

LaborEtArs
LaborEtArs

Reputation: 2043

Quite old question, but maybe a solution is helpful to others too...

An UITableView does create cell, header and footer views only if they are needed (e.g. they are visible in the table view content area).

If the cell, header or footer view isn't visible in the table view, a call to 'cellForRowAtIndexPath:', 'headerViewForSection:' or 'footerViewForSection:' might return 'nil'. (See UITableView.h for documentation of this behaviour. The only exception would be, that the view has not jet been recycled by the table view)

Of course you can create any table view subview by calling the responsible delegate method directly, but UITableView wouldn't do so by itself.

So the solution to access a cell, header oder footer view is to make it visible in the table view first.

An example for an header view:

CGRect  sectionHeaderRect = [self.tableView rectForHeaderInSection:groupSectionIndex];
[self.tableView scrollRectToVisible:sectionHeaderRect
                           animated:NO];

// Let the tableview load the needed views
dispatch_async(dispatch_get_main_queue(), ^{

    UITableViewHeaderFooterView*    groupSectionHeaderView = [self.tableView headerViewForSection:sectionIndex];

    // Use groupSectionHeaderView
});

Upvotes: 8

cjd
cjd

Reputation: 549

heightForRowAtIndexPath called before viewForHeaderInSection so of course you will get nil.

Upvotes: -1

Keith Kennedy
Keith Kennedy

Reputation: 320

Where are you calling [tableView headerViewForSection:indexPath.section];?

If you are calling it in - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath before the tableView is visible then you will get nil back as the tableView is not setup yet.

If you call it else where once the tableView is loaded, you should get a UITableViewHeaderFooterView back.

Upvotes: 0

Nikita
Nikita

Reputation: 1853

Have you implemented

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section

and

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

in your ViewController subclass?

And if yes, probably you have some problem in one of these methods.

Upvotes: 2

Related Questions