15

I have a UITableView that displays checkmarks when a row is selected. The problem is that When i select a row in didSelectRowAtIndexPath and add a checkmark on the selected row it adds an additional checkmark. Here's my code

Any help would be very much appreciated.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];

    // Configure the cell...

    cell.textLabel.text=[[Model.category objectAtIndex:indexPath.row] categoryName];

    cell.imageView.image=[[Model.category objectAtIndex:indexPath.row]categoryImage];

    //cell.detailTextLabel.text =@"Breve Descripción de la categoria";

    return cell;

}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{

    if ([self.tableView cellForRowAtIndexPath:indexPath].accessoryType == UITableViewCellAccessoryCheckmark) {

 [self.tableView cellForRowAtIndexPath:indexPath].accessoryType =UITableViewCellAccessoryNone;

 [self.cellSelected removeObject:indexPath];

    }else {

     [tableView cellForRowAtIndexPath:indexPath].accessoryType=UITableViewCellAccessoryCheckmark;

        [self.cellSelected addObject:indexPath];

    }

   [self checkMark];

   [tableView reloadData];   
}

- (void)checkMark{

    for (NSIndexPath * indexPath in self.cellSelected) {

       [self.tableView cellForRowAtIndexPath:indexPath].accessoryType=UITableViewCellAccessoryCheckmark;

    }


}
slugonamission
  • 9,562
  • 1
  • 34
  • 41
Klinkert0728
  • 326
  • 1
  • 4
  • 14

2 Answers2

41

[self.tableView cellForRowAtIndexPath:indexPath] call in the didSelectRowAtIndexPath will not return the exact cell. It can be same cell, new cell or reused cell. If it is a reused cell at its accessory view has a checkmark, you will end up having two cells with checkmark.

Its better to store in the array and use it accordingly. If you are planning to have multiple selections, Use the code example below.

- (void)viewDidLoad
{
    [super viewDidLoad];

// Do any additional setup after loading the view, typically from a nib.
    self.cellSelected = [NSMutableArray array];
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
   //Cell Initialisation here

    if ([self.cellSelected containsObject:indexPath])
    {
      cell.accessoryType = UITableViewCellAccessoryCheckmark;
    }
    else
    {
      cell.accessoryType = UITableViewCellAccessoryNone;

    }
    return cell;
}


 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
    //if you want only one cell to be selected use a local NSIndexPath property instead of array. and use the code below
   //self.selectedIndexPath = indexPath;

    //the below code will allow multiple selection
    if ([self.cellSelected containsObject:indexPath])
    {
      [self.cellSelected removeObject:indexPath];
    }
    else
    {
       [self.cellSelected addObject:indexPath];
    }
    [tableView reloadData];
}
Hiren
  • 12,720
  • 7
  • 52
  • 72
nprd
  • 1,942
  • 1
  • 13
  • 16
  • why is [tableView deselectRowAtIndexPath:indexPath animated:YES] necessary?? when I comment this line it works well too. – Klinkert0728 May 19 '14 at 02:52
  • I'm having the same problem, but with an Image, i have an image for each cell and when I select a row i need to change the image of the selected row, but when i change this image, also another image change maybe you can help me – Klinkert0728 Jun 13 '14 at 21:53
  • deselect is to remove the highlighted behavior when you touch the cell. – nprd Jun 14 '14 at 12:47
  • Klinkert0728 Need to look at your code to find the actual problem you are facing. – nprd Jun 14 '14 at 12:48
  • Instead of reloading the whole tableView, wouldn't it be better to just reload the selected row with "reloadRowsAtIndexPaths"? – tf.alves Nov 17 '15 at 08:43
4

Try this:

Declare in your .m file:

@interface MyViewController () {
        NSIndexPath *__selectedPath;
    }

In tableView:cellForRowAtIndexPath: check if given indexPath is the same as stored in ivar:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {       
    //configure cell

    if ([__selectedPath isEqual:indexPath]) {
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
    } else {
        cell.accessoryType = UITableViewCellAccessoryNone;
    }

    return cell;
}

In tableView:didSelectRowAtIndexPath store pointer to selected NSIndexPath or nil if cell has been deselect

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

    if (cell.accessoryType == UITableViewCellAccessoryNone) {
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
        __selectedPath = indexPath;
    } else {
        cell.accessoryType = UITableViewCellAccessoryNone;
        __selectedPath = nil;
    }
}

I wrote it without checking in Xcode, so there could be some typos, but I show main idea. In my opinion you shouldn't call [self checkMark]; in your tableView:cellForRowAtIndexPath: method.

Moreover if you want to have only one selected cell at a time, you should't create NSMutableArray to store NSIndexPath. It seems yours cellSelected stores 2 NSIndexPaths at a time, that why you have this strange behaviour.

Neru
  • 679
  • 6
  • 19
  • Thank you very much, but i need to call the method checkMark because i have a MutableArray with indexPath depending on which cell was selected, and i need those cells with check mark. I'm new with all this hope you can help me. – Klinkert0728 May 18 '14 at 22:40
  • If you want have only one cell selected at once, don't use NSMutableArray. Just NSIndexPath. NSMutableArray takes much more space in memory, hence it is not needed to use it here. Moreover when using NSIndexPath you will be sure that only one pointer to NSIndexPath will be stored, and during your tableView reloading data, only one or zero UITableViewCell will be selected. – Neru May 18 '14 at 22:45