Simon
Simon

Reputation: 6523

UITableViewCell accessory checkmark not saving on scroll after selecting row

I am storing at most only 3 items that are allowed to be checked at anytime.

I store the selected rows in an NSMutabeDictionary called selectedRowDictionary in didSelectRowAtIndexPath

Then in my cellForRowAtIndexPath

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"identifer" forIndexPath:indexPath];

if (_selectedRowDictionary && [_selectedRowDictionary count]) {
    for (NSString *rowSelected in _selectedRowDictionary) {
        BOOL isRowSelected = [[_selectedRowDictionary valueForKey:rowSelected] integerValue];
        if (isRowSelected){
            NSLog(@"rowSelected: %@", rowSelected);
        } else {
            NSLog(@"rowNotSelected: %@", rowSelected);
        }

        int rowIndexSelected = [[rowSelected substringFromIndex:[rowSelected length] - 1 ] integerValue];

        if (isRowSelected && rowIndexSelected == indexPath.row) {
            cell.accessoryType = UITableViewCellAccessoryCheckmark;
        } else {
            cell.accessoryType = UITableViewCellAccessoryNone;
        }
    }
}    
return cell;
}

- - didSelectRowAtIndexPath:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];


if (cell.accessoryType == UITableViewCellAccessoryCheckmark) {
    cell.accessoryType = UITableViewCellAccessoryNone;

    if (_selectedRowDictionary) {
        [_selectedRowDictionary removeObjectForKey:[NSString stringWithFormat:@"row%d", indexPath.row]];
        NSLog(@"row %d removed from array", indexPath.row);
    }

} else {
    cell.accessoryType = UITableViewCellAccessoryCheckmark;
    [_selectedRowDictionary setValue:[NSNumber numberWithBool:YES] forKey:[NSString stringWithFormat:@"row%d", indexPath.row]];
}

if ([_selectedRowDictionary count] > 3) {
    UITableViewCell *lastSelectedCell = [tableView cellForRowAtIndexPath:indexPath];
    lastSelectedCell.accessoryType = UITableViewCellAccessoryNone;

    [_selectedRowDictionary removeObjectForKey:[NSString stringWithFormat:@"row%d", indexPath.row]];
    NSLog(@"row selected > 3, row%d not selected", indexPath.row);
}
}

Am I missing something that is causing the cell to be deselected again when I scroll down the tableview?

When I NSLog the dictionary, it says that those rows exist and have been selected

I have checked similar questions but, I thought I solved the cell recycling issue already.

Upvotes: 0

Views: 126

Answers (2)

norders
norders

Reputation: 1252

Are you at liberty to use a mutable array instead?

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

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

    if ([_selectedRowArray containsObject:indexPath])
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
    else
        cell.accessoryType = UITableViewCellAccessoryNone;

    return cell;
}


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

    if ([_selectedRowArray containsObject:indexPath]) {
        [_selectedRowArray removeObject:indexPath];
    } else {
        if (_selectedRowArray.count < 3)
            [_selectedRowArray addObject:indexPath];
        else {
            // Don't select it
        }
    }

    [tableView reloadData]; 
}

Upvotes: 1

AshokPolu
AshokPolu

Reputation: 645

I am editing your code, try this code.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
   UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"identifer" forIndexPath:indexPath];
   BOOL isRowSelected = [[_selectedRowDictionary valueForKey:@(indexPath.row)] boolValue]
   if (isRowSelected) {
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
    } else {
        cell.accessoryType = UITableViewCellAccessoryNone;
    }  
   return cell;
}

Code changes in --didSelectRowAtIndexPath

    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];


if (cell.accessoryType == UITableViewCellAccessoryCheckmark) {
    cell.accessoryType = UITableViewCellAccessoryNone;

    if (_selectedRowDictionary) {
        [_selectedRowDictionary removeObjectForKey:@(indexPath.row)];
        NSLog(@"row %d removed from array", indexPath.row);
    }

} else {
    if (_selectedRowDictionary.count == 3) {
       // Don't allow for Selection
       return;
    }
    cell.accessoryType = UITableViewCellAccessoryCheckmark;
    [_selectedRowDictionary setValue:@(YES) forKey:@(indexPath.row)];
   }
}

User has to unselect the previous selected row to select new row. I edited your code in optimised way, I hope this code works for you.

Upvotes: 1

Related Questions