Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UITableView Checkmark ONLY ONE Row at a Time

Tags:

With this code, I can check multiple rows in a table.

But what I want is to only have one row checked at a time. Here's my code:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
    
    UITableViewCell *theCell = [tableView cellForRowAtIndexPath:indexPath];
    
    if (theCell.accessoryType == UITableViewCellAccessoryNone) {
        theCell.accessoryType = UITableViewCellAccessoryCheckmark;
    } else if (theCell.accessoryType == UITableViewCellAccessoryCheckmark) {
        theCell.accessoryType = UITableViewCellAccessoryNone;
    }
}

If a user selects a different row, then I want the old row to simply automatically uncheck. Don't know how to do that.

like image 450
Jupiter869 Avatar asked Apr 17 '12 14:04

Jupiter869


4 Answers

Objective-C:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath   *)indexPath {      [tableView cellForRowAtIndexPath:indexPath].accessoryType = UITableViewCellAccessoryCheckmark; }  -(void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath  {     [tableView cellForRowAtIndexPath:indexPath].accessoryType = UITableViewCellAccessoryNone; } 

Swift:

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {     tableView.cellForRow(at: indexPath)?.accessoryType = .checkmark }  func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {     tableView.cellForRow(at: indexPath)?.accessoryType = .none } 
like image 93
Ujwal Manjunath Avatar answered Sep 21 '22 15:09

Ujwal Manjunath


You can create a new variable to track the index selected at didSelectRowAtIndex.

int selectedIndex; 

in your cellForRowAtIndexPath

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

and in your didSelectRowAtIndex

selectedIndex = indexPath.row; [tableView reloadData]; 
like image 45
John Paul Manoza Avatar answered Sep 17 '22 15:09

John Paul Manoza


The best way is to set the accessory type in cellForRowAtIndexPath.

Use didSelectRowAtIndexPath to only record which path should be selected and then call reloadData.

like image 34
Phillip Mills Avatar answered Sep 19 '22 15:09

Phillip Mills


You don't need to (and shouldn't) just reload the table after each selection.

Apple has good documentation on how to manage a selection list. See Listing 6-3 for an example.

This is more or less the same answer as some of the others but I thought I'd add a little more detail.

What you want to do is save the current selected IndexPath to a variable and use that in didSelectRowAtIndexPath to remove the old check mark. This is also where you will be adding the new check mark.

You need to make sure to also set/unset the checkmarks in cellForRowAtIndexPath otherwise if your list is large and cells are reused it will look like multiple rows are selected. This is a problem with some of the other answers.

See swift 2.0 example below:

// for saving currently seletcted index path
var selectedIndexPath: NSIndexPath? = NSIndexPath(forRow: 0, inSection: 0)  // you wouldn't normally initialize it here, this is just so this code snip works
// likely you would set this during cellForRowAtIndexPath when you dequeue the cell that matches a saved user selection or the default

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    // this gets rid of the grey row selection.  You can add the delegate didDeselectRowAtIndexPath if you want something to happen on deselection
    tableView.deselectRowAtIndexPath(indexPath, animated: true) // animated to true makes the grey fade out, set to false for it to immediately go away

    // if they are selecting the same row again, there is nothing to do, just keep it checked
    if indexPath == selectedIndexPath {
        return
    }

    // toggle old one off and the new one on
    let newCell = tableView.cellForRowAtIndexPath(indexPath)
    if newCell?.accessoryType == UITableViewCellAccessoryType.None {
        newCell?.accessoryType = UITableViewCellAccessoryType.Checkmark
    }
    let oldCell = tableView.cellForRowAtIndexPath(selectedIndexPath!)
    if oldCell?.accessoryType == UITableViewCellAccessoryType.Checkmark {
        oldCell?.accessoryType = UITableViewCellAccessoryType.None
    }

    selectedIndexPath = indexPath  // save the selected index path

    // do whatever else you need to do upon a new selection
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)
    // if this is the currently selected indexPath, set the checkmark, otherwise remove it
    if indexPath == selectedIndexPath {
        cell.accessoryType = UITableViewCellAccessoryType.Checkmark
    } else {
        cell.accessoryType = UITableViewCellAccessoryType.None
    }
}
like image 35
jeffjv Avatar answered Sep 19 '22 15:09

jeffjv