简体   繁体   中英

Checkmark on TableView is repeating when scrolling

Edit: Added an else statement to remove the checkmark. However, now, it doesn't repeat the checkmarks anymore, but if two or more cells are marked and I scroll down and back up, it removes all of them except one. Any ideas why? I am having a hard time understanding cell recycling, when this happens.

I've been pulling my hair out at this problem, as I am just not able to figure it out. Any pointers or help would be greatly appreciated.

Everytime I choose a cell and scroll, it repeats the checkmark randomly. I am deciding if a cell needs a checkmark, by checking the indexPath.row with an array that contains the indexPath.row + 1.

Updating the titles and descriptions when scrolling works just fine, it's just the checkmarks that are acting up.

This is my current code for cellForRowAtIndexPath:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *simpleTableIdentifier = @"KnuterItem";
    if([s.taskArray valueForKey:@"TaskData"] != [NSNull null])
    {
        KJBasicCell *cell = (KJBasicCell*)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];

        // Add utility buttons
        NSMutableArray *rightUtilityButtons = [NSMutableArray new];

        [rightUtilityButtons sw_addUtilityButtonWithColor:
         [UIColor colorWithRed:1.0f green:0.231f blue:0.188 alpha:1.0f]
                                                    title:@"Les mer"];

        cell.rightUtilityButtons = rightUtilityButtons;
        cell.delegate = self;

        if (cell == nil) {

            NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"KnuterItem" owner:self options:nil];
            cell = [nib objectAtIndex:0];
        }

        NSDictionary    *item = [s.taskArray objectAtIndex:indexPath.row];

        if([item objectForKey:@"Title"] != [NSNull null])
            cell.titleLabel.text = [item objectForKey:@"Title"];
                if(s.textColor)
                    cell.titleLabel.textColor = s.textColor;

        if([item objectForKey:@"Description"] != [NSNull null]){
            if (s.isNotAutoRowHeight == 0) {
                cell.descLabel.numberOfLines = 0;
            } else {
                cell.descLabel.numberOfLines = 1;
            }
            cell.descLabel.text = [item objectForKey:@"Description"];
                if(s.textColor)
                    cell.descLabel.textColor = s.textColor;
            cell.descriptionText = [item objectForKey:@"Description"];
        }

        if([[s.selfArray valueForKey:@"CheckStat"] isEqualToString:@"(null)"])
        {
            cell.accessoryType = UITableViewCellAccessoryNone;
        }
        else if([[s.selfArray valueForKey:@"CheckStat"] length] == 0)
        {
            if ([[item objectForKey:@"CheckStat"] containsString:@"1"])
                cell.accessoryType = UITableViewCellAccessoryCheckmark;
            else
                cell.accessoryType = UITableViewCellAccessoryNone;
        }
        else
        {
            NSLog(@"array: %@", [s.selfArray valueForKey:@"CheckStat"]);
            for(int i = 0; i < [[[s.selfArray valueForKey:@"CheckStat"] componentsSeparatedByString:@","] count]; i++)
            {
                NSString    *checkedNumStr = [[[s.selfArray valueForKey:@"CheckStat"] componentsSeparatedByString:@","] objectAtIndex:i];
                if ([checkedNumStr intValue] == indexPath.row + 1)
                        cell.accessoryType = UITableViewCellAccessoryCheckmark;
                else
                    cell.accessoryType = UITableViewCellAccessoryNone;
            }
        }


        return cell;
    }
    else
        return  nil;
}

didSelectRowAtIndex:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
    if(cell.accessoryType == UITableViewCellAccessoryCheckmark)
    {
        cell.accessoryType = UITableViewCellAccessoryNone;
    }
    else
    {
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
    }
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
    CheckStatStr = nil;
    for(int i = 0; i < [s.taskArray count]; i++)
    {
        NSIndexPath *eachPath = [NSIndexPath indexPathForRow:i inSection:0] ;
        UITableViewCell *eachCell = [tableView cellForRowAtIndexPath:eachPath];
        if(eachCell.accessoryType == UITableViewCellAccessoryCheckmark)
        {
            if([CheckStatStr length] == 0 || !CheckStatStr)
            {
                CheckStatStr = [[NSMutableString alloc] init];
                [CheckStatStr setString:(NSString*)[NSString stringWithFormat:@"%d",i+1]];
            }
            else
                [CheckStatStr appendString:[NSString stringWithFormat:@",%d",i+1]];
        }
    }
    if(CheckStatStr){
        s.OldCheckStatStr = [s.selfArray valueForKey:@"CheckStat"];
        [s.selfArray setValue:CheckStatStr forKey:@"CheckStat"];
    }else{
        [s.selfArray setValue:@"0" forKey:@"CheckStat"];
    }
}

When you check if ([checkedNumStr intValue] == indexPath.row + 1) and set add the checkmark, you need to set cell.accessoryType = UITableViewCellAccessoryNone if it isn't.

if ([checkedNumStr intValue] == indexPath.row + 1)
    cell.accessoryType = UITableViewCellAccessoryCheckmark;
else
    cell.accessoryType = UITableViewCellAccessoryNone;

Table view cells get reused, so if a cell that has a checkmark is reused for a row that you don't want to have a checkmark you need to remove the checkmark.

Without looking at the source, I can tell you are a victim of cell recycling. Apple does this for performance reasons, make sure that you deselect the cell in tableView:cellForRowAtIndexPath: (remove the checkmark) if it shouldn't be checked, otherwise it will retain the checkmark when recycling another cell.
cell.accessoryType = UITableViewCellAccessoryNone

Edit with more code:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
    if(cell.accessoryType == UITableViewCellAccessoryCheckmark)
    {
        cell.accessoryType = UITableViewCellAccessoryNone;
    }
    else
    {
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
    }
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
    s.taskArray[indexPath.row][@"CheckStat"] = @YES
}

Another cause of this is if there's any layer backed effects (ie animations)... Click on the CB itself and pop open the "View effects inspector".. In there you should see a list of CA (core animation) layers..

If you've toyed with the rendering of the CB's then, I'd suggest you either look in there and enable the correct layers, or reconnect the badly rendered rendition :D

With Swift 3.0,

cell.accessoryType = UITableViewCellAccessoryNone;

becomes

`cell.accessoryType = UITableViewCellAccessoryType.none

How I solve This Issue in Swift 5

Main Reason of repeating checkmark is cell reusable . then displaying cell resuse and checkmark Still Apear . How I resolve this issue :

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let cell = self.schedulTable.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
        as! scheduleCell

    cell.timeLable.text = self.timeArray[indexPath.row]
    // here is the code which clear checkmark on reuse
    if item.num >= 0 && item.isSelected == true{
        if item.num == indexPath.row{
            cell.accessoryType = .checkmark
        }else{
             cell.accessoryType = .none
        }
    }


       return cell
   }



 func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
 selected_Time = self.timeArray[indexPath.row]
    item.isSelected = true
   item.num = indexPath.row
    schedulTable.cellForRow(at: indexPath)?.accessoryType = .checkmark
  //schedulTable.reloadData()

}

func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
    schedulTable.cellForRow(at: indexPath)?.accessoryType = .none
}


struct Item {
 var num : Int
 var isSelected : Bool
init() {
    num = -1
    isSelected = false
}}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM