pheedsta
pheedsta

Reputation: 2080

Custom UITableViewCell not displaying correctly when UITableViewController first loads

I have created a custom UITableViewCell using the following code:

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {

        mapButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];       
        [[self contentView] addSubview:mapButton];        

        houseNumberLabel = [[UILabel alloc] initWithFrame:CGRectZero];
        [[self contentView] addSubview:houseNumberLabel];
        [houseNumberLabel release];

        NSArray *segmentArray = [[NSArray alloc] initWithObjects:@"Yes", @"No", nil];
        segmentedControl = [[UISegmentedControl alloc] initWithItems:segmentArray];
        [segmentArray release];
        [segmentedControl setSegmentedControlStyle:UISegmentedControlStyleBar];
        [[self contentView] addSubview:segmentedControl];
        [segmentedControl release];

        disclosureButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure]; 
        [[self contentView] addSubview:disclosureButton];              
    }

    return self;
}

I have then overridden the layoutSubviews method in the custom cell with the following code:

- (void)layoutSubviews
{
    [super layoutSubviews];

    CGRect viewBounds = [[self contentView] bounds];
    float h = viewBounds.size.height;
    float w = viewBounds.size.width;

    float inset = 20.0;
    float mapButtonWidth = mapButton.frame.size.width;
    float segmentWidth = 140.0;
    float disclosureButtonWidth = disclosureButton.frame.size.width;
    float houseNumberLabelWidth = viewBounds.size.width - (mapButtonWidth + inset + inset + segmentWidth + inset + disclosureButtonWidth + inset);

    CGRect frame = CGRectMake(0, 0, h, mapButtonWidth);
    [mapButton setFrame:frame];

    frame.origin.x += mapButtonWidth + inset;
    frame.size.width = houseNumberLabelWidth;
    [houseNumberLabel setFrame:frame];

    frame.origin.x += houseNumberLabelWidth + inset;
    frame.size.width = segmentWidth;
    [segmentedControl setFrame:frame];

    frame.origin.x += segmentWidth + inset;
    frame.size.width = disclosureButtonWidth;
    [disclosureButton setFrame:frame];
}

I have added logs to these functions and they are being called each time a cell is created. The problem is when the UITableViewController first loads and displays the cells the cells are displaying formatted as if layoutSubviews was never called (even though according to the log it has). However, when I scroll through the table view the new cells (that were offscreen) display correctly. I then scroll back and the first cells are now correct. It is as if layoutSubviews is being called but when the table view is first loaded it fails to realise it needs to render using the new layout.

I have added a reloadData to viewWillAppear which partially fixes the problem however the last cell (that is just off screen) still renders the incorrect way. I am pulling my hair out.

[SUBNOTE] I just added a log to:

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath

And this is running 8 times (one for each cell being displayed first for the table view) BEFORE layoutSubviews is being called. layoutSubviews is being called after this (hence why the format is incorrect). Should I add a [cell layoutSubviews] in here (it does work but it is then called again after) or is there another way?

Upvotes: 1

Views: 746

Answers (1)

pheedsta
pheedsta

Reputation: 2080

I worked it out (I am a little embarrassed at the mistake) but I was initially setting the CGRect dimensions incorrectly. I was putting height for width and width for height. The code should be:

CGRect frame = CGRectMake(0, 0, mapButtonWidth, h);

An easy enough mistake to make but one that produces unusual results.

Upvotes: 0

Related Questions