Pham Hoan
Pham Hoan

Reputation: 2127

ios - UITableViewCell display wrong data when scrolling

Here's my code:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifierNormal = @"CellNormal";
static NSString *CellIdentifierTracking = @"CellTracking";

switch (self.mapState) {
    case MapStateNormal:
    {
//            UITableViewCell *cell = [self.table dequeueReusableCellWithIdentifier:CellIdentifierNormal];
//            if (cell == nil) {
            UITableViewCell *cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifierNormal];
//            }
        [cell.textLabel setText:@"abc"];
        return cell;
    }
    case MapStateTracking:
    {
//            UITableViewCell *cell = [self.table dequeueReusableCellWithIdentifier:CellIdentifierTracking];
//            if (cell == nil) {
            UITableViewCell *cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifierTracking];
//            }
        if (indexPath.row == 0) {
            [cell.textLabel setText:@"Lorem ipsum"];
        } else {
            NSURL *url = [LoremIpsum URLForPlaceholderImageFromService:LoremIpsumPlaceholderImageServicePlaceKittenCom
                                                             withWidth:1024
                                                                height:1024];
            [cell.imageView setImageWithURL:url
                           placeholderImage:[UIImage imageNamed:@"MenuButton"]];
           }
        return cell;
    }
    default:
        break;
}
return nil;
}

This piece of code works fine but not the best practice because I re-create UITableViewCell everytime. It display like this:

Correct Display

However, when I uncomment those lines above to enable dequeueReusableCell then the table shows its cells with errors like this (the yellow part is my code):

enter image description here enter image description here

You can see that there's an UIImage in first row and text in some rows below while I clearly didn't set it in my code.

What could I do to fix this ? or should I stick with the first method ?

Thanks.

Upvotes: 3

Views: 2470

Answers (3)

Akhilrajtr
Akhilrajtr

Reputation: 5182

Try this, clear the cell if it cell != nil

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifierNormal = @"CellNormal";
static NSString *CellIdentifierTracking = @"CellTracking";

switch (self.mapState) {
    case MapStateNormal:
    {
            UITableViewCell *cell = [self.table dequeueReusableCellWithIdentifier:CellIdentifierNormal];
            if (cell == nil) {
                UITableViewCell *cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifierNormal];
            } else {
                [cell.textLabel setText:@""];
                [cell.imageView setImage:nil];
            }
            ...
        return cell;
    }

    case MapStateTracking:
    {
            UITableViewCell *cell = [self.table dequeueReusableCellWithIdentifier:CellIdentifierTracking];
            if (cell == nil) {
                UITableViewCell *cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifierTracking];
            } else {
                [cell.textLabel setText:@""];
                [cell.imageView setImage:nil];
            }
            ....
        return cell;
    }
    default:
        break;
}
return nil;
}

Upvotes: 1

Reinhard Männer
Reinhard Männer

Reputation: 15227

You should really re-use the table view cells, because it is a lot of overhead if you recreate them all the time, i.e. the out-commented code is right.
Next, the docs say: "The table view's delegate in tableView:cellForRowAtIndexPath: should always reset all content when reusing a cell."
If you do not reset the content, it will be shown again.
So I suggest that you set

cell.imageView.image = nil; 

in your -(UITableViewCell *)tableView:cellForRowAtIndexPath:(NSIndexPath *)indexPath method.

Upvotes: 6

Kirsteins
Kirsteins

Reputation: 27335

Simply set [cell.textLabel setText:@""]; for each cell you dont't want to display any text. Cells are reused with the previous text, so you need to clear it.

Upvotes: 1

Related Questions