wowzuzz
wowzuzz

Reputation: 1388

Keep selected state of UITableViewCells when scrolling

I am trying to keep the selected state of multiple cells on a didSelectRowAtIndexPath method. I have an edit button that I've set up that loops through every cell to select each field on my UITableView.

Here is the code for the edit button on tap that selects all my rows.

- (IBAction)editButtonTapped:(id)sender {

for (int i = 0; i < self.caseDataTableView.numberOfSections; i++) {
    for (NSInteger r = 0; r < [self.caseDataTableView numberOfRowsInSection:i]; r++) {
        [self tableView:caseDataTableView didSelectRowAtIndexPath:[NSIndexPath indexPathForRow:r inSection:i]];
    }
}

}

When calling the didSelectRowAtIndexPath method, it does the following code.

    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
OKOperatieNoteTableViewCell *cell = (OKOperatieNoteTableViewCell *)[self.caseDataTableView cellForRowAtIndexPath:indexPath];
cell.cellIndexPath = indexPath;
[cell hideLabelAndShowButtons];}

Incase you were wondering here is the hideLabelAndShowButtons method.

- (void)hideLabelAndShowButtons {
self.caseDataKeyLabel.hidden = NO;

if (!self.disabled) {
    self.caseDataValueLabel.hidden = YES;
    self.textField.hidden = NO;
    if ([self.inputType isEqualToString:@"switcher"] || [self.inputType isEqualToString:@"multiselect"] || [self.inputType isEqualToString:@"picker"] || [self.inputType isEqualToString:@"DatePicker"] || [self.inputType isEqualToString:@"selectContact"]) {
        self.button.hidden = NO;
    }else {
        self.button.hidden = YES;
    }
}

self.caseDataDescriptionTextView.hidden = YES;}

Now at this point, I have all my rows selected. If I scroll down and then back up the selection of these rows is not there anymore. Now I'm aware when you go in and out of the view, the cellForRowAtIndexPath method recreates these cells. The following is my cellForRowAtIndexPath method.

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

static NSString *cellIdentifier = @"caseData";
OKOperatieNoteTableViewCell * cell = [[OKOperatieNoteTableViewCell alloc]init];

cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];

if (indexPath.row < _procedureVariables.count) {
    if ([[[_caseDataArray objectAtIndex:indexPath.row] valueForKey:@"key"] isEqualToString:@"Procedure"]) {
        [cell setLabelsWithKey:[[_caseDataArray objectAtIndex:indexPath.row] valueForKey:@"key"] AndValue:[self.model valueForKey:@"var_procedureName"]];
    }else {
        [cell setLabelsWithKey:[[_caseDataArray objectAtIndex:indexPath.row] valueForKey:@"key"] AndValue:[[_caseDataArray objectAtIndex:indexPath.row] valueForKey:@"value"]];
    }

    OKProcedureTemplateVariablesModel *variableModel = _procedureVariables[indexPath.row];
    cell.variable = variableModel.value;
    [cell showLabelAndHideButtons];
    cell.delegate = self;
    [cell setUpCellType];
} else if (indexPath.row == _procedureVariables.count) {
    NSString *text = [NSString stringWithFormat:@"%@ \n\n %@", [_templateDictionary objectForKey:@"indicationText"], [_templateDictionary objectForKey:@"procedureText"] ];
    [cell showDescription:text];
    NSLog(@"cell.caseDataDescriptionTextView.font.fontName = %@", cell.caseDataDescriptionTextView.font.fontName);
}

cell.procedureID = _procedureID;
[tableView setContentInset:UIEdgeInsetsMake(1.0, 0.0, 0.0, 0.0)];

return cell;

}

I'm just trying to figure out how to keep the selected state of these cells once the cellForRowAtIndexPath method is called. Any suggestions are welcomed.

Upvotes: 0

Views: 1754

Answers (3)

meth
meth

Reputation: 1885

i tried to simulate your situation, created a customCell and saved the indexpaths of selectedRows in my custom selectedPaths mutable array(initialized in viewDidLoad). After every click i removed or added related indexpath to my array. it worked for my case. Hope it helps.

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *cellIdentifier = @"caseData";
    NOTableViewCell *cell = (NOTableViewCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    if (cell == nil)
    {
        NSLog(@"new cell created for row %d", (int)indexPath.row);
        cell = [[[NSBundle mainBundle] loadNibNamed:@"NOTableViewCell" owner:self options:nil] objectAtIndex:0];
    }
    if ([selectedPaths indexOfObject:indexPath] != NSNotFound) // this cell is in selected state. 
    {
        [cell.textLabel setText:@"This cell selected"];//selected state job.
        return cell;
    }
        [cell.textLabel setText:[NSString stringWithFormat:@"%d", (int)indexPath.row]];
    return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{

    if ([selectedPaths indexOfObject:indexPath] != NSNotFound) {
        [selectedPaths removeObject:indexPath];
    }
    else{
        [selectedPaths addObject:indexPath];
    }
    //[tableView reloadData];

    [tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];//instead of reloading all just reload clicked cell.
}

Upvotes: 3

Paulw11
Paulw11

Reputation: 114846

While you are invoking the delegate method in order to call hideLabelAndShowButtons, you aren't telling the table view that you have selected the row;

- (IBAction)editButtonTapped:(id)sender {

    for (int i = 0; i < self.caseDataTableView.numberOfSections; i++) {
        for (NSInteger r = 0; r < [self.caseDataTableView numberOfRowsInSection:i]; r++) {
            NSIndexPath *path=[NSIndexPath indexPathForRow:r inSection:i];
            [caseDataTableView selectRowAtIndexPath:path animated:NO scrollPosition:UITableViewScrollPositionNone];
            [self tableView:caseDataTableView didSelectRowAtIndexPath:path];
        }
    }
 }

Also, you aren't using the cell selection state in cellForRowAtIndexPath, so you probably need to change some code there too, but I am not sure what the relationship is between selected state and how you want to render the cell.

Upvotes: 0

Mundi
Mundi

Reputation: 80265

You need to update the cell to selected and not selected explicitly in both directions in cellForRowAtIndexPath.

If not, the recycled cells will just show the value of the cell the cell was last used for until you change it.

Upvotes: 1

Related Questions