views:

399

answers:

1

I'm trying to add checkmarks to items when the user select rows in a table view. However, the view is not refreshed and the checkmarks do no show up:

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

    UITableViewCell* oldCell = [self tableView:tv cellForRowAtIndexPath:[NSIndexPath indexPathForRow:selectedIndex inSection:0]];
    oldCell.accessoryType = UITableViewCellAccessoryNone;

    if (indexPath.section == 0) {
        selectedIndex = indexPath.row;
    }

    UITableViewCell* newCell = [self tableView:tv cellForRowAtIndexPath:indexPath];
    newCell.accessoryType = UITableViewCellAccessoryCheckmark;

    [tv deselectRowAtIndexPath:indexPath animated:NO];
}

What could be a reason for that?

+3  A: 

Call cellForRowAtIndexPath directly on the tv object instead of through self to make sure you get a proper cell reference back:

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

    UITableViewCell *oldCell = [tv cellForRowAtIndexPath:[NSIndexPath indexPathForRow:selectedIndex inSection:0]];
    oldCell.accessoryType = UITableViewCellAccessoryNone;

    if (indexPath.section == 0) {
        selectedIndex = indexPath.row;
    }

    UITableViewCell *newCell = [tv cellForRowAtIndexPath:indexPath];
    newCell.accessoryType = UITableViewCellAccessoryCheckmark;

    [tv deselectRowAtIndexPath:indexPath animated:NO];
}

Also make sure that in cellForRowAtIndexPath, you have this logic:

...
if (indexPath.row == selectedIndex)
    cell.accessoryType = UITableViewCellAccessoryCheckmark;
else
    cell.accessoryType = UITableViewCellAccessoryNone;
...
return cell;

otherwise, a checkmark will remain on a cell after it scrolls off the screen and comes back on screen even after you've selected another cell.

DyingCactus
Agreed, and from what I can see ALL of the code in didSelectRowAtIndexPath needs to go save the deselectRowAtIndexPath. What should happen is when a row is selected, call [tv reloadData]; and let cellForRowAtIndexPath do it all.
Kenny
Calling reloadData everytime you check or uncheck an item is a bad idea if you can just as easily set the checkmark manually without recreating every visible cell.
Ed Marty
How different is it to call cellForRowAtIndexPath directly on tv or the way I was doing it? Anyways, it solved my problem, so thank you.
Kamchatka
@Kamchatka: [This post](http://stackoverflow.com/questions/2198618/why-some-method-declarations-in-the-uitableviewdatasource-protocol-are-preceded-b/2198704#2198704) by Jasarien explains the difference.
DyingCactus