Question

I have a UITableViewController with scrolling enabled, embedded within a UIContainerView. Within the tableview there is a custom UITableViewCell which has a UIImageView inside, when you select one of multiple cells in the tableview, I get the index path and set the image view of the selected cell to show a tick. The table view is dynamically populated with multiple pieces of data from an array. Simple.

Problem is, because the tableview is longer than can be visible within the container view, it would seem that the the index path is being applied only for the visible content. Meaning that it is setting the cell with a the corresponding index path to the visible one with a tick also.

Say five cells are visible, number four is selected. You go down five more cells and there is a tick applied to what should be the tenth cell but is technically the fifth cell of the non visible content. I presume it's something to do with cell reusage but I'm not sure what to do.

How does one go about fixing this? (Code is as below)

    - (void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    CuisineTableCell *cell  = [tableView cellForRowAtIndexPath:indexPath];
    //Store current view in defaults
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

    if (cuisineSelected == NO) {
        cuisineSelected = YES;
        cell.imageView.image = [UIImage imageNamed:@"TickedCircle"];
        //Set cuisine one defaults
        [defaults setObject:[cuisinesArray objectAtIndex:indexPath.row] forKey:@"filterCuisineString"];
        [defaults synchronize];
        selectedRow = [tableView indexPathForSelectedRow];
    }
    else if(indexPath.row == selectedRow.row) {
        cuisineSelected = NO;
        cell.imageView.image = [UIImage imageNamed:@"UntickedCircle"];
        //Set cuisine one defaults
        [defaults setObject:@"" forKey:@"filterCuisineString"];
        [defaults synchronize];
        selectedRow = NULL;
    }
    else {
        CuisineTableCell *selectedCell  = [tableView cellForRowAtIndexPath:selectedRow];
        selectedCell.imageView.image = [UIImage imageNamed:@"UntickedCircle"];
        // the one and only cell in the section
        cuisineSelected = YES;
        cell.imageView.image = [UIImage imageNamed:@"TickedCircle"];
        //Set cuisine one defaults
        [defaults setObject:[cuisinesArray objectAtIndex:indexPath.row] forKey:@"filterCuisineString"];
        [defaults synchronize];
        selectedRow = [tableView indexPathForSelectedRow];
    }
}

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

    if (cuisineSelected == NO) {
        cell.imageView.image = [UIImage imageNamed:@"UntickedCircle"];
    }
    cell.textLabel.text = [cuisinesArray objectAtIndex:indexPath.row];

    return cell;
}
Was it helpful?

Solution

Because the Cell is being reused ALL parts of if need to be set or unset, if it reuses the cell and the tick is there then it will display again. Note that if you have 20 rows but only 4 are on the screen iOS will draw only draw a few of them and as one scrolls of it is reused for the next one coming on.

Much of your didSelect.... is not needed.

Change to this;

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

    if (indexPath.row == selectedRow.row) {  // if you have sections then compare the whole indexPath
        cell.imageView.image = [UIImage imageNamed:@"TickedCircle"];
    }
    else
    {
        cell.imageView.image = [UIImage imageNamed:@"UntickedCircle"];
    }
    cell.textLabel.text = [cuisinesArray objectAtIndex:indexPath.row];

    return cell;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top