1

I have a given number of cells in a section. My goal is to have only the last selected cell to display a checkmark. The other cells should not.

I have found a function in this similar but older thread. I've modified it (and I bet here lies the problem) slightly because of the changes in Swift 3.0.

As it is written below, for me, the function does not work properly. Only the last cell (not last selected, but last in section) in the section will ever get the checkmark. But I cannot figure out why not.

Here is the full function:

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    let section = indexPath.section
    let numberOfRows = tableView.numberOfRows(inSection: section)
    for row in 0..<numberOfRows {
        if let cell = tableView.cellForRow(at: indexPath) {
            cell.accessoryType = row == indexPath.row ? .checkmark : .none
        }
    }
}

By printing out the values I can see when this statement below evaluates to true, and it makes sense. But the checkmark does not get toggled.

    cell.accessoryType = row == indexPath.row ? .checkmark : .none

Thank you!

Community
  • 1
  • 1
user1269290
  • 451
  • 1
  • 6
  • 18

2 Answers2

1

First tell your tableview it can only select one cell at a time:

override func viewDidLoad() {
    super.viewDidLoad()

    self.tableView.allowsMultipleSelection = false
}

Then, let's analyse your code, you're getting the section at which the present cell is being selected and calculating the number of rows in that specific section. You iterate on the rows of that section and checking if you have a cell at the given indexPath (I guess it always evaluates to true because you always have a cell at that indexPath, you didn't put a condition depending on the value of your for-loop). Then you tell the cell to have a checkmark if the row in the for-loop equals the row of the cell being currently selected by the user. As your function is written, there is no reason why only the last in the section would get the checkmark, but you overcomplicated the matter.

Your cell is drawn in the following method and so should the accessory initially.

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "YourCell", for: indexPath)

    cell.textLabel?.text = "your text"

    cell.accessoryType = cell.isSelected ? .checkmark : .none
    // cell.selectionStyle = .none if you want to avoid the cell being highlighted on selection then uncomment

    return cell
  }

Then you can just say that the accessory type should be .checkmark in tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) and .none in tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath).Here is how to do it and you should be good, if not let me know and I can edit again.

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    tableView.cellForRowAtIndexPath(indexPath)?.accessoryType = .checkmark
}

override func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
    tableView.cellForRowAtIndexPath(indexPath)?.accessoryType = .none
}
Ocunidee
  • 1,769
  • 18
  • 20
  • Ocunidee, thanks for the attempt. I am not even close to where you are. I am still not clear about the basics of tableviews at this point. Right now I am just really curious why the code I posted is not doing what I am thinking it should. – user1269290 Jan 07 '17 at 02:40
  • Oh right, I had misunderstood what you were asking for. What one time, you want only one cell to be selected (checkmark showing) ? You have to tell your tableview you are not allowing multiple selection: – Ocunidee Jan 07 '17 at 09:55
  • @user1269290 have you found a solution? – Ocunidee Jan 12 '17 at 11:56
  • Sorry I had no time to attend to this thread the last few days.This works great! Thank you! Your syntax is not Swift 3.0, but it works. – user1269290 Jan 13 '17 at 17:58
0

Swift 4.x
Xcode 12

func viewDidLoad() {
 tableView.allowsMultipleSelection = false
}

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    tvAmbientSoundTableView.cellForRow(at: indexPath)?.accessoryType = .checkmark
}

func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
    tvAmbientSoundTableView.cellForRow(at: indexPath)?.accessoryType = .checkmark
}
Abdul Karim
  • 4,359
  • 1
  • 40
  • 55