Nic Hubbard
Nic Hubbard

Reputation: 42173

UITableViewCell duplicated over and over

I am creating my cells from an array. The last object in my area gets created differently, as I want to add a new UILabel to the contentView of the cell. (So that it shows a total number of records in a UILabel in the last cell).

For some reason, my last cell that adds the UILabel to the contentView keeps getting duplicated. It will show up on other cells, screw up their display, etc. I have a feeling this has to do with cell reuse, but I am not sure how to fix it.

Here is my method:

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

    // Bounds
    CGRect bounds = [[UIScreen mainScreen] bounds];

    Person *person = nil;
    if (tableView == self.searchDisplayController.searchResultsTableView) {
        person = [people objectAtIndex:indexPath.row];
    }

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellID];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:kCellID] autorelease];
        cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;

        // Check if it is the first cell
        if (person == [people lastObject]) {
            cell.accessoryType = UITableViewCellAccessoryNone;
            cell.userInteractionEnabled = NO;

            UILabel *count = [[UILabel alloc] initWithFrame:CGRectMake(-4, 11, bounds.size.width - 10, 20)];
            count.autoresizingMask = UIViewAutoresizingFlexibleWidth;
            count.textColor = [UIColor darkGrayColor];
            count.font = [UIFont systemFontOfSize:16];
            count.textAlignment = UITextAlignmentCenter;
            count.text = person.nameFirst;
            cell.textLabel.text = nil;
            cell.detailTextLabel.text = nil;
            [cell.contentView addSubview:count];

            return cell;
        }

    }//end

    cell.textLabel.text = [NSString stringWithFormat:@"%@, %@", person.nameLast, person.nameFirst];

    // Check if they are faculty staff
    if ([person.status isEqualToString:@"Staff/Faculty"]) {
        cell.detailTextLabel.text = [NSString stringWithFormat:@"%@: %@", person.status, person.department];
    } else {
        cell.detailTextLabel.text = person.status;
    }//end

    return cell;
}

Can someone help me understand how I can get this working correctly so that my UILabel doesn't get created on different cells?

Upvotes: 1

Views: 1897

Answers (2)

theChrisKent
theChrisKent

Reputation: 15099

I have adjusted your method below. Basically, you need to dequeue cells and perform any cell wide settings (disclosure, etc.) when you create the cell. Any individual cell changes should be done after the cell has been dequeued.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *kCellID = @"cellID";
    static NSString *lastCellID = @"lastcellID";

    // Bounds
    CGRect bounds = [[UIScreen mainScreen] bounds];

    Person *person = nil;
    if (tableView == self.searchDisplayController.searchResultsTableView) {
        person = [people objectAtIndex:indexPath.row];
    }

    UITableViewCell *cell;

    if (person != [people lastObject]) {
        cell = [tableView dequeueReusableCellWithIdentifier:kCellID];
        if (cell == nil) {
            cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:kCellID] autorelease];
            cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
        }
        cell.textLabel.text = [NSString stringWithFormat:@"%@, %@", person.nameLast, person.nameFirst];

        // Check if they are faculty staff
        if ([person.status isEqualToString:@"Staff/Faculty"]) {
            cell.detailTextLabel.text = [NSString stringWithFormat:@"%@: %@", person.status, person.department];
        } else {
            cell.detailTextLabel.text = person.status;
        }//end
    } else {
        cell = [tableView dequeueReusableCellWithIdentifier:lastCellID];
        if (cell == nil) {
           cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:lastCellID] autorelease];
           cell.accessoryType = UITableViewCellAccessoryNone;
           cell.userInteractionEnabled = NO;

            UILabel *count = [[UILabel alloc] initWithFrame:CGRectMake(-4, 11, bounds.size.width - 10, 20)];
            count.autoresizingMask = UIViewAutoresizingFlexibleWidth;
            count.textColor = [UIColor darkGrayColor];
            count.font = [UIFont systemFontOfSize:16];
            count.textAlignment = UITextAlignmentCenter;
            count.tag = 1;
            [cell.contentView addSubview:count];
        }
        UILabel *count = (UILabel *)[cell viewWithTag:1];
        count.text = person.nameFirst;
        //cell.textLabel.text = nil;
        //cell.detailTextLabel.text = nil;
    }//end

    return cell;
}

Upvotes: 2

MHC
MHC

Reputation: 6405

It's probably because the cell will be reused. Use a different reuse identifier for the last cell, say, kLastCellID.

UITableViewCell *cell = nil;
// Check if it is the first cell
if (person == [people lastObject]) {
    cell = [tableView dequeueReusableCellWithIdentifier:kLastCellID];
    if (!cell) {
        //create a last cell, with an UILabel in your content view
    }
    //update the cell's content
} else {
    cell = [tableView dequeueReusableCellWithIdentifier:kCellID];
    if (!cell) {
        //create a regular cell
    }
    //update the cell's content
}

Upvotes: 2

Related Questions