Objective-C: UITableView cells get written over each time when scrolling up and down

南楼画角 提交于 2019-12-06 00:03:38

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

This line is telling your app to reuse existing offscreen cells if they exist. So basically you are taking an already existing cell and adding a new subview to it in the same place that a subview already exits. You need to clear out the existing subviews before adding your new subview.

Update in answer to your comment:

jan's code will remove the existing subviews. You would add it to your code above as the else clause of your if cell is nil statement.

So if you don't have a reusable cell available (cell == nil), your code will create a new one, else your code will remove the old subviews from the existing cell:

if (cell == nil) {
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
        cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    cell.textLabel.font = [UIFont boldSystemFontOfSize:12];
}
else {
    UIView* subview;
    while ((subview = [[[cell contentView] subviews] lastObject]) != nil)
      [subview removeFromSuperview];
}

an alternate, more terse way of achieving the same thing would be:

if (cell == nil) {
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    cell.textLabel.font = [UIFont boldSystemFontOfSize:12];
}
else {
    [[[cell contentView] subviews] makeObjectsPerformSelector: @selector(removeFromSuperview)];
}

It's because the cell is being cached and you keep adding to the content view without removing what has already been added.

You can either use a more specific cell identifier and add to the content view only on cell creation or clear out the content view before adding the labels again.

To clear a cell's subviews you can add this:

if(cell == nil)
{...}
else
{
    UIView* subview;
    while ((subview = [[[cell contentView] subviews] lastObject]) != nil)
      [subview removeFromSuperview];
}

When cell != nil that means it is a cell you've already created and added sub views to, that's why they need to be cleared.

When ever we use reuse identifier for UITableView,it understands that the cell needs to be reused and the values in the cells overwritten with one another when we are not specifying index values of the cell identifier to be reused.

We need to specifically tell the table view cell,to reuse the cell at index path,i.e.

NSString *cellIdentifier = [NSString stringWithFormat:@"S%1dR%1d",indexPath.section,indexPath.row];

and use this cell identifier in if(cell == nil)

UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellIdentifier:cellidentifier];

This would eliminate the mis communication among cells and values in cells doesn't get over written with one another.More over this avoids the hassle of communication between index locations or cell index values.Hope this helps,thanks :)

Dont want to autorelease the UITableViewCell because your app may crash when scrolling multiple times and change the position of device .

You can remove the subview in else condition when cell is not nil.

static NSString *CellIdentifier = @"CellIdentifier";        
UITableViewCell  *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    //create  a uitableviewcell
    if(cell == nil)
    {
     //Do whatever you want to do 

    }else{
        [[cell.contentView viewWithTag:YOUR_TAG] removeFromSuperview];
    }
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!