AndroidDev
AndroidDev

Reputation: 21247

UITableViewCell Reuse Cell Repeated Values

I'm having a classic problem with the reuse of a UITableViewCell. I know what the problem is, but I cannot figure out what I am doing wrong or how to fix it. When the screen first renders, everything looks great. But as the user scrolls, the same image and text displays repeatedly in sets of 8 rows.

Towards the end of the method, I print out the text value that is supposed to be displayed. This value looks great, as does the indexPath.row value. I just can't get the cells to be reused correctly.

I've left off the image refresh code, since it is little complex and not really relevant to the main issue. Please focus on the text updating, and I'm sure that the image updating will follow a similar pattern.

I think that I am setting up the cells correctly. Each subview is only added inside the cell==nil block. Then, I attempt to change the text outside of this block. But somehow it's not getting the correct pointer reference??? I'm stuck.

- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *cellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

    MyObject *obj = [self.fetchedObjects objectAtIndex:indexPath.row];
    UILabel *name;
    UIImageView *imgView;

    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];

        name = [[UILabel alloc] init];
        name.frame = CGRectMake(40, 0.0, _tableView.frame.size.width-40, 44);
        name.adjustsFontSizeToFitWidth = YES;
        name.minimumScaleFactor = 0.5;
        [cell addSubview:name];

        imgView = [[UIImageView alloc] init];
        imgView.frame = CGRectMake(0, 4, 36, 36);
        imgView.image = [UIImage imageNamed:@"myimage.png"];
        [imgView setContentMode:UIViewContentModeScaleAspectFit];
        [cell addSubview:imgView];
    }

    // this has to be outside the `cell == nil` block, right???        
    name.text = obj.name;

    // this output is perfect - but the actual cells are repeated!
    NSLog(@"indexpath: %d", indexPath.row);
    NSLog(@"name from array: %@", obj.name);

    return cell;
}

Upvotes: 0

Views: 869

Answers (2)

Kjuly
Kjuly

Reputation: 35181

// this has to be outside the cell == nil block, right???
name.text = obj.name;

It's incorrect. When the cell is not nil, the name label & image view are not alloced at all. If u persist to do like this, there's indeed a way can solve your issue (using view tag):

UILabel *name;
UIImageView *imgView;
NSInteger nameTag    = 101;
NSInteger imgViewTag = 102;

if (cell == nil) {
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];

    name = [[UILabel alloc] init];
    name.tag = nameTag;
    ...
    [cell addSubview:name];

    imgView = [[UIImageView alloc] init];
    imgView.tag = imgViewTag;
    ...
    [cell addSubview:imgView];
}
else {
  name    = (UILabel *)[cell viewWithTag:nameTag];
  imgView = (UIImageView *)[cell viewWithTag:imgViewTag];
}

name.text = obj.name;
...

BUT

I think you don't need to create new label & image view for the cell, there's imageView & textLabel available for the UITableViewCell. You can just update their value like this:

if (cell == nil) {
  // ...
}

cell.textLabel.text  = obj.name;
cell.imageView.image = obj.image;

And if u want to relayout the textLabel & imageView, u can create a subclass inherit from UITableViewCell, and override the -layoutSubviews:

- (void)layoutSubviews
{
  [super layoutSubviews];

  // modify textLabel & imageView's frame
}

Upvotes: 1

rmaddy
rmaddy

Reputation: 318944

As written, the name and imgView values will be nil for reused cells.

You need an else added to your if statement to set name and imgView by accessing the existing views from the cell.

Upvotes: 3

Related Questions