tommi
tommi

Reputation: 6973

Weird behavior from UITableView

I'm trying to print a UITableView with two distinct types of UITableViewCells.

  1. Empty table view cells that contains nothing (first 2 cell), just a black background
  2. Table view cells that contains a label, an image, etc. beginning from 1 (3rd and subsequent cells)

The height of my table view is able to fit at least 3 table view cells at anyone time.

When I first load the table view, the table view looks perfectly fine - 1st two rows are black, follow by the 3rd row which has the label that says "1".

However, after scrolling down to the bottom then scrolling back up. My first two empty cells (which are supposed to be empty) are filled with things that should only be found in the 3rd and subsequent cells.

I suspect this behavior is coming from the table view reusing cells but I'm still unable to figure it out.

Code snippets:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
    }    

    switch ([indexPath row]) {
        case 0:
            cell.contentView.backgroundColor = [UIColor blackColor];
            [cell setSelectionStyle:UITableViewCellSelectionStyleNone]; 
            break;
        case 1:
            cell.contentView.backgroundColor = [UIColor blackColor];
            [cell setSelectionStyle:UITableViewCellSelectionStyleNone]; 
            break;

        default:
            cell.contentView.backgroundColor = [UIColor blackColor];
            [cell setSelectionStyle:UITableViewCellSelectionStyleNone]; 

            UILabel *rowLabel = [[UILabel alloc] initWithFrame:CGRectMake(25, 30, 200, 30)];
            rowLabel.text = [NSString stringWithFormat:@"Row %d", [indexPath row]-1];
            rowLabel.backgroundColor = [UIColor blackColor];
            rowLabel.textColor = [UIColor whiteColor];
            [rowLabel setFont:[UIFont fontWithName:@"GillSans-Bold" size:18]];
            [cell.contentView rowLabel];                 [rowLabel release];

            UIButton *aButton = [[UIButton alloc] initWithFrame:CGRectMake(100, 50, 40, 40)];
            [aButton setImage:anImage forState:UIControlStateNormal];
            [cell.contentView addSubview:aButton];
            [aButton release];

            break;
    }

    return cell;
}

Upvotes: 1

Views: 597

Answers (2)

jrturton
jrturton

Reputation: 119242

Your dequeued cells will still contain all of the buttons and labels you added, all you are doing is setting the background colour when the cell is dequeued.

You have a few options:

  • Use a tableHeaderView for your black area
  • Use a grouped table view with sections
  • Use a different reuse identifier for cells at row 0 and 1.

For the latter option, your cellForRowAtIndexPath should be:

static NSString *CellIdentifier = @"Cell";
static NSString *blankCellIndentifier = @"BlankCell";

if (indexPath.row == 0 || indexPath.row == 1)
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:blankCellIdentifier];
    if (cell == nil)
    {
        cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:blankCellIdentifier] autorelease];
        cell.contentView.backgroundColor = [UIColor blackColor];
        [cell setSelectionStyle:UITableViewCellSelectionStyleNone];
    }
return cell;
}
else
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    UILabel *rowLabel;
    UIButton *aButton;

    if (cell == nil) 
    {
        // Here, you create all of the new objects
        cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
        cell.contentView.backgroundColor = [UIColor blackColor];
        [cell setSelectionStyle:UITableViewCellSelectionStyleNone]; 
        rowLabel = [[UILabel alloc] initWithFrame:CGRectMake(25, 30, 200, 30)];
        rowLabel.backgroundColor = [UIColor blackColor];
        rowLabel.textColor = [UIColor whiteColor];
        [rowLabel setFont:[UIFont fontWithName:@"GillSans-Bold" size:18]];
        [cell.contentView addSubview:rowLabel];
        rowLabel.tag = 1;
        [rowLabel release];

        aButton = [[UIButton alloc] initWithFrame:CGRectMake(100, 50, 40, 40)];
        [aButton setImage:anImage forState:UIControlStateNormal];
        [cell.contentView addSubview:aButton];
        aButton.tag = 2;
        [aButton release];

    }
    // Here, you just configure the objects as appropriate for the row 
    rowLabel = (UILabel*)[cell.contentView viewWithTag:1];
    rowLabel.text = [NSString stringWithFormat:@"Row %d", [indexPath row]-1];

    return cell;
}

Upvotes: 1

Benjamin Mayo
Benjamin Mayo

Reputation: 6679

For each different type of cell, you need a different reuse identifier. So, your case you need three reuseIdentifier's.

Upvotes: 0

Related Questions