-1

I have the following implementation where user could able to select as many item as he wants.

I could able to see checkmark once user selects the item, however when user scroll up or down, there is a strange behavior because I see other items are selected as well, even though it is not selected.

For example, if I select 3 items in order, when I scroll down, I could able to see same pattern (3 items in order) selected. is it something related with dequeueReusableCellWithIdentifier ? If yes, what I am doing wrong?

- (void)viewDidLoad {

    [super viewDidLoad];
    self.comboTableView.allowsMultipleSelection = YES;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath   *)indexPath
{
    [comboTableView cellForRowAtIndexPath:indexPath].accessoryType = UITableViewCellAccessoryCheckmark;
}
-(void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [comboTableView cellForRowAtIndexPath:indexPath].accessoryType = UITableViewCellAccessoryNone;
 }

-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return movies.count;
}

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return ((Section*)movies[section]).movies.count ;
}

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

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

    cell.textLabel.text =  ((Section*)movies[indexPath.section]).movies[indexPath.row];
    return cell;
}
casillas
  • 16,351
  • 19
  • 115
  • 215

2 Answers2

3

UITableView Cells are reused because you are using dequeueReusableCellWithIdentifier:cellIdentifier. So you have to check whether the current index path item selected or not. If selected then enable tick mark. else disable it

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

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

    NSArray <NSIndexPath*> *selectedIndexPaths = [tableView indexPathsForSelectedRows];

    if ([selectedIndexPaths containsObject:indexPath]) {
            // Add the code of enable tick mark
    } else {
            // Add the code of disable tick mark
    }
}
Subramanian P
  • 4,365
  • 2
  • 21
  • 25
1

This problem is because you 'check the tableviewcell' but not your data. So if you doesn't record this check information, your tableviewcell will record the check status even if this cell instance changed to present different data of different indexPath.

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath   *)indexPath
{
    [comboTableView cellForRowAtIndexPath:indexPath].accessoryType = UITableViewCellAccessoryCheckmark;
    ((Section*)movies[indexPath.section]).movies[indexPath.row].checked = true;
}
-(void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [comboTableView cellForRowAtIndexPath:indexPath].accessoryType = UITableViewCellAccessoryNone;
    ((Section*)movies[indexPath.section]).movies[indexPath.row].checked = false;
 }

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

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

    cell.textLabel.text =  ((Section*)movies[indexPath.section]).movies[indexPath.row];
    cell.accessoryType = ((Section*)movies[indexPath.section]).movies[indexPath.row].checked ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;
    return cell;
}
Codus
  • 1,433
  • 1
  • 14
  • 18
  • do I really keep track of each selection in my data by adding another variable in my model class, or just leave tableview handles it for me? I have upvoted your effort – casillas Jul 12 '17 at 06:05
  • Yes, you should record because tableview doesn't handle this for you. That's why you confused. – Codus Jul 12 '17 at 06:07
  • `[tableView indexPathsForSelectedRows]` stores selected `section` and `row` (indexPath), does not it? – casillas Jul 12 '17 at 06:08
  • I made a mistake in your words. yes you can use [tableView indexPathsForSelectedRows]. – Codus Jul 12 '17 at 06:11
  • I am just trying to be a fair by selecting the best answer. Your answer is also right, but the accepted answer slightly better. – casillas Jul 12 '17 at 06:13
  • 1
    Yes i agree! you're right! :) – Codus Jul 12 '17 at 06:14