0

I'm trying to allow only one UITableViewCell to be checked at a time in a section. What I'm going for is to uncheck a checked UITableViewCell (if there is one) and checking the current selected cell. So basically, If one CellA is selected, and I select CellB, I want CellA to unselect and CellB to select.

Here's what I've done to try and accomplish this:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    if(![self.selectedIndexPaths containsObject:indexPath]) {
        [self.selectedIndexPaths addObject:indexPath];
    }
    else {
        [self.selectedIndexPaths removeObject:indexPath];
    }

    if (indexPath.section == 0) {
        [tableView cellForRowAtIndexPath:indexPath].accessoryView.hidden = NO; 
    }
    else if (indexPath.section == 1) {
        if (![self.selectedIndexPaths containsObject:indexPath]) {
            [tableView cellForRowAtIndexPath:indexPath].accessoryView.hidden = NO;
        }
        else {
            for (NSIndexPath *indexPath2 in self.selectedIndexPaths) {
                if (indexPath2.section == 1) {
                    [tableView cellForRowAtIndexPath:indexPath2].accessoryView.hidden = YES;
                    [tableView cellForRowAtIndexPath:indexPath].accessoryView.hidden = NO;
                }
            }
        }
    }
    else if (indexPath.section == 2) {
        if (![self.selectedIndexPaths containsObject:indexPath]) {
            [tableView cellForRowAtIndexPath:indexPath].accessoryView.hidden = NO;
        }
        else {
            for (NSIndexPath *indexPath2 in self.selectedIndexPaths) {
                if (indexPath2.section == 2) {
                    [tableView cellForRowAtIndexPath:indexPath2].accessoryView.hidden = YES;
                    [tableView cellForRowAtIndexPath:indexPath].accessoryView.hidden = NO;
                }
            }
        }

    }

}

-(void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath {
    if (indexPath.section == 0) {
        if ([tableView cellForRowAtIndexPath:indexPath].accessoryView.hidden == YES) {
            [tableView cellForRowAtIndexPath:indexPath].accessoryView.hidden = NO;
        }
        else {
            [tableView cellForRowAtIndexPath:indexPath].accessoryView.hidden = YES;
        }
    }
    else if (indexPath.section == 1) {
        if (![self.selectedIndexPaths containsObject:indexPath] && [tableView cellForRowAtIndexPath:indexPath].accessoryView.hidden == YES) {
            [tableView cellForRowAtIndexPath:indexPath].accessoryView.hidden = NO;
        }
        else if (![self.selectedIndexPaths containsObject:indexPath] && [tableView cellForRowAtIndexPath:indexPath].accessoryView.hidden == NO){
            [tableView cellForRowAtIndexPath:indexPath].accessoryView.hidden = YES;
        }
        else {
            for (NSIndexPath *indexPath2 in self.selectedIndexPaths) {
                if (indexPath2.section == 1 && [tableView cellForRowAtIndexPath:indexPath2].accessoryView.hidden == YES) {
                    [tableView cellForRowAtIndexPath:indexPath].accessoryView.hidden = NO;
                }
            }
        }
    }
    else if (indexPath.section == 2) {
        if (![self.selectedIndexPaths containsObject:indexPath] && [tableView cellForRowAtIndexPath:indexPath].accessoryView.hidden == YES) {
            [tableView cellForRowAtIndexPath:indexPath].accessoryView.hidden = NO;
        }
        else if (![self.selectedIndexPaths containsObject:indexPath] && [tableView cellForRowAtIndexPath:indexPath].accessoryView.hidden == NO){
            [tableView cellForRowAtIndexPath:indexPath].accessoryView.hidden = YES;
        }
        else {
            for (NSIndexPath *indexPath2 in self.selectedIndexPaths) {
                if (indexPath2.section == 2 && [tableView cellForRowAtIndexPath:indexPath2].accessoryView.hidden == YES) {
                    [tableView cellForRowAtIndexPath:indexPath].accessoryView.hidden = NO;
                }
            }
        }

    }
}

As you can see, I have three sections, and the first one the user can select however many cells they want, but in the second and third, it's limited to one.

The Issue: Whenever I select a cell and then another cell, it works. If I select the first cell, both of them are now checked.

I would appreciate any help or suggestions. Thanks!

1 Answers1

1

Your code looks a lot more complicated than it needs to be. I would do it by creating a property (of type NSIndexPath) for sections 1 and 2, and an array property for section 0 to keep track of the selected cell or cells in the respective sections. Set the value of the properties with the indexPath, or add the indexPath in the case of the array, when a cell is tapped (or delete it if it's already checked). Then check the state of those properties or array in cellForRowAtIndexPath.

@interface TableController ()
@property (strong,nonatomic) NSArray *theData;
@property (strong,nonatomic) NSIndexPath *selectedPathForSection1;
@property (strong,nonatomic) NSIndexPath *selectedPathForSection2;
@property (strong,nonatomic) NSMutableArray *selectedPaths;
@end

@implementation TableController 


- (void)viewDidLoad {
    [super viewDidLoad];
    self.selectedPaths = [NSMutableArray new];
    self.selectedPathForSection1 = nil;
    self.selectedPathForSection2 = nil;
}


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

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
    cell.textLabel.text = self.theData[indexPath.section][indexPath.row];
    if ([self.selectedPathForSection1 isEqual:indexPath] || [self.selectedPathForSection2 isEqual:indexPath] || [self.selectedPaths containsObject:indexPath]) {
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
    }else{
        cell.accessoryType = UITableViewCellAccessoryNone;
    }
    return cell;
}



- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    switch (indexPath.section) {
        case 0:
            if (! [self.selectedPaths containsObject:indexPath]) {
                [self.selectedPaths addObject:indexPath];
            }else{
                [self.selectedPaths removeObject:indexPath];
            }
            break;
        case 1:
            if (![self.selectedPathForSection1 isEqual:indexPath]) {
                self.selectedPathForSection1 = indexPath;
            }else{
                self.selectedPathForSection1 = nil;
            }
            break;
        case 2:
            if (![self.selectedPathForSection2 isEqual:indexPath]) {
                self.selectedPathForSection2 = indexPath;
            }else{
                self.selectedPathForSection2 = nil;
            }
            break;
    }
    [tableView reloadData];
}
rdelmar
  • 103,982
  • 12
  • 207
  • 218
  • Thanks, I'll give it a spin... Do I have to reloadData? – user2242965 Sep 05 '13 at 01:20
  • @user2242965, yes, you have to reload the data to see the change (or if you want to be more efficient you can use reloadRowsAtIndexPaths, but that takes a bit more code). – rdelmar Sep 05 '13 at 01:23
  • I'm trying to slightly modify this to make it so if one cell is selected in section 3 (self.selectedPathSpecial) - all of the other checkmarks disappear... Great, that works. However, when I try to make self.selectedPathSpecial disappear (if any other cell in the UITableView is selected) by doing `self.selectedPathSpecial = nil;` the checkmark doesn't disappear from the cell... any ideas? – user2242965 Sep 06 '13 at 04:33
  • @user2242965, did you reload the data after that statement? Other than that, I can't say what might be wrong without seeing your code. – rdelmar Sep 06 '13 at 04:55
  • @user2242965, you don't have any logic to do what you say you want -- the only condition where you set selectedPathSpecial to nil is when you click on that cell and it's already checked. You would have to add that line (self.selectedPathSpecial = nil) to all the other cases where you're setting one of the other properties (where you set the property to indexPath or add an indexPAth to the array). – rdelmar Sep 06 '13 at 15:12
  • I'm sorry, that was outdated - this is what I currently have: http://hastebin.com/xedopakuni.m (and it still doesn't work) - thanks for your reply – user2242965 Sep 06 '13 at 16:16
  • @user2242965, I don't see anything wrong with that code. What are you now doing in cellForRowAtIndexPath? – rdelmar Sep 06 '13 at 19:21
  • I'm using the same code in your answer I just added || [self.selectedPathSpecial isEqual:indexPath] – user2242965 Sep 06 '13 at 19:49
  • Any idea what's going on? – user2242965 Sep 06 '13 at 21:06
  • @user2242965, You forgot the break statement in case 1, adding that in fixed the problem. – rdelmar Sep 07 '13 at 01:19