UITableViewCell checkmark change on select

Am I correct in thinking that to change the checkmark for "on" to "off", I must change the CellAccessoryType between none and checkmark on the didSelectRowAtIndexPath?

Because I have done this but I have noticed the behaviour is not perfectly identical to like the checkmark cells on the auto lock settings on the iphone.

Or is there some other way checkmarks are meant to be handled?


Solution 1:

  1. Keep a property in your view controller called selectedRow, which represents the index of a row that represents the checked item in a table section.

  2. In your view controller's -tableView:cellForRowAtIndexPath: delegate method, set the accessoryType of the cell to UITableViewCellAccessoryCheckmark if the cell's indexPath.row equals the selectedRow value. Otherwise, set it to UITableViewCellAccessoryNone.

  3. In your view controller's -tableView:didSelectRowAtIndexPath: delegate method, set the selectedRow value to the indexPath.row that is selected, e.g.: self.selectedRow = indexPath.row

Solution 2:

Another solution:

-(NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    NSIndexPath *oldIndex = [self.tableView indexPathForSelectedRow];
    [self.tableView cellForRowAtIndexPath:oldIndex].accessoryType = UITableViewCellAccessoryNone;
    [self.tableView cellForRowAtIndexPath:indexPath].accessoryType = UITableViewCellAccessoryCheckmark;
    return indexPath;
}

And yeah: you don't have to check if oldIndex is nil :)


Swift 3 and later:

override func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
    if let oldIndex = tableView.indexPathForSelectedRow {
        tableView.cellForRow(at: oldIndex)?.accessoryType = .none
    }
    tableView.cellForRow(at: indexPath)?.accessoryType = .checkmark

    return indexPath
}