user8000557
user8000557

Reputation: 137

UITableView checkmarks duplicated

I keep getting checkmarks being marked in other sections of my table view when I click a row. Im not certain if I need to set my accessoryType. I tried mytableView.reloadData() however that didn't help either.

 var selected = [String]()
 var userList = [Users]()

@IBOutlet weak var myTableView: UITableView!

@IBAction func createGroup(_ sender: Any) {

    for username in self.selected{

        ref?.child("Group").childByAutoId().setValue(username)

        print(username)
    }

}
 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let myCell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! MyTableViewCell
    myCell.selectionStyle = UITableViewCellSelectionStyle.none
    myCell.nameLabel.text = userList[indexPath.row].name
    return myCell
}

 func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    if myTableView.cellForRow(at: indexPath)?.accessoryType == UITableViewCellAccessoryType.checkmark{

        myTableView.cellForRow(at: indexPath)?.accessoryType = UITableViewCellAccessoryType.none
       let currentUser = userList[indexPath.row]
        selected = selected.filter { $0 != currentUser.name}
    }
    else{
        myTableView.cellForRow(at: indexPath)?.accessoryType = UITableViewCellAccessoryType.checkmark
        let currentUser = userList[indexPath.row]
        selected.append(currentUser.name!)
    }
            }

Upvotes: 1

Views: 836

Answers (2)

Jen Jose
Jen Jose

Reputation: 4045

The issue is you are not maintaining the selected User info properly, which will be used while you scroll the table and when the cell has to reload data.

As you have already created var selected = [String]() , I suggest using the same.

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let myCell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! MyTableViewCell
    let dataFoundInselectedArr =  selected.filter { $0 == userList[indexPath.row].name}

    if(dataFoundInselectedArr.count > 0){
          myCell.accessoryType = UITableViewCellSelectionStyle.checkmark
    }else{
          myCell.accessoryType = UITableViewCellSelectionStyle.none
    }

    myCell.nameLabel.text = userList[indexPath.row].name
    return myCell
}

The table selection delegate method remains the same.

Upvotes: 0

Pochi
Pochi

Reputation: 13459

Your problem is not inside this method but in the one that "loads" the cells. (cell for row)

Since Table Views use reusable cells, more often than not they will be loading a cell that was already presented somewhere else.

Because of this, on the cell loading method you should "Reset the state" the loaded cell, this includes the accessory type, and any other properties you might have changed.

So just change this in your code:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let myCell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! MyTableViewCell
    myCell.selectionStyle = UITableViewCellSelectionStyle.none
    myCell.nameLabel.text = userList[indexPath.row].name

    // ADD THIS
    if userList[indexPath.row].isSelected {
        myCell.accessoryType = UITableViewCellAccessoryType.checkmark
    } else {
        myCell.accessoryType = UITableViewCellAccessoryType.none
    }

    return myCell
}

EDIT:

"userList[indexPath.row].isSelected" is a property that YOU have to create and manage. (So you must also modify it in the didSelectRowAt method.

Upvotes: 2

Related Questions