Single and MultiSelection cells in same tableView | Swift

Viewed 42

Before duplicating this question, please be known that I've spent days on this issue, working hours, and looking for all same sort of questions on SO, but there is something I am missing or doing wrong.

I have a tableView in which the data is being populated via API response. Below is the model I have.

struct Model : Codable {
   let bugClassification : [Bug]?
}

struct Bug : Codable {
  let selectable : String?  //Telling wether cell is single/Multi selected
  var options : [Options]?
}

struct Options : Codable, Equatable {
  let title : String?
  let id: Int
  var isCellSelected: Bool = false
}

Scenario I want to create multiple sections, each having different cell depending upon the type of selectable, either single or multi. I have achieved that, but the problem I am getting is that whenever I scroll, random cells are also selected. Now, I know this behaviour is because of tableView reusing the cells. But I am confused as how to handle all this. Also, I want to put the validation on the sections, that is, every section should have atleast one cell selected. Kindly guide me in the right direction, and any small help would be appreciated. Below is my code.

CellForRowAt

 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    if bugClassification[indexPath.section].selectable?.lowercased() == "multi-select" {
        //Multi-Selection
        let cell = tableView.dequeueReusableCell(withIdentifier: multiSelectionCellID) as! MultiSelectionCell
        let item = bugClassification[indexPath.section].options![indexPath.row]
        cell.label.text = item.title
        if item.isCellSelected {
            cell.checkMarkImageView.alpha = 1
            cell.checkMarkView.layer.borderColor = UIColor.white.cgColor
            cell.checkMarkView.backgroundColor = .emerald
        } else if item.isCellSelected {
            cell.checkMarkImageView.alpha = 0
            cell.checkMarkView.layer.borderColor = UIColor.veryLightBlue.cgColor
            cell.checkMarkView.backgroundColor = .white
        }
        return cell
    } else {
        //Single-Selection
        let cell = tableView.dequeueReusableCell(withIdentifier: singleSelectionCellID) as! SingleSelectionCell
        let item = bugClassification[indexPath.section].options![indexPath.row]
        cell.label.text = item.title
        if item.isCellSelected {
            cell.checkMarkImageView.alpha = 1
            cell.checkMarkView.layer.borderColor = UIColor.emerald.cgColor
        } else {
            cell.checkMarkImageView.alpha = 0
            cell.checkMarkView.layer.borderColor = UIColor.veryLightBlue.cgColor
        }
        return cell
    }
}

DidSelectRow Method

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    if bugClassification[indexPath.section].selectable?.lowercased() == "multi-select" {
        var item = bugClassification[indexPath.section].options![indexPath.row]
        item.isCellSelected = !item.isCellSelected
        bugClassification[indexPath.section].options![indexPath.row] = item
        self.tableView.reloadRows(at: [indexPath], with: .automatic)
       
    } else {
        let items = bugClassification[indexPath.section].options
        if let selectedItemIndex = items!.indices.first(where: { items![$0].isCellSelected }) {
            bugClassification[indexPath.section].options![selectedItemIndex].isCellSelected = false
            if selectedItemIndex != indexPath.row {
                bugClassification[indexPath.section].options![indexPath.row].isCellSelected = true
            }
        } else {
            bugClassification[indexPath.section].options![indexPath.row].isCellSelected = true
        }
        self.tableView.reloadSections([indexPath.section], with: .automatic)
    }
}
1 Answers

In cellForRowAt

if item.isCellSelected == true{
                cell.accessoryType = .checkmark
            } else {
                cell.accessoryType = .none
            }

and update the model by every selection

func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
    let item = bugClassification[indexPath.section].options![indexPath.row]
                    if let cell = tableView.cellForRow(at: indexPath) {
                        cell.accessoryType = .none
                        if indexPath.section == 0{
                            item.isCellSelected.isSelected = false
                        }else{
                            item.isCellSelected.isSelected = false
                        }
                    }
                }
 func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    let item = bugClassification[indexPath.section].options![indexPath.row]
                    if let cell = tableView.cellForRow(at: indexPath) {
                        cell.accessoryType = .checkmark
                        if indexPath.section == 0{
                            item.isCellSelected.isSelected = true
                        }else{
                            item.isCellSelected.isSelected = true
                        }
                    }
                }
Related