BVB09
BVB09

Reputation: 875

Swiping a UITableViewCell action affects every 4th cell in the table view instead of ONLY the target cell

I have a weird situation where I swipe a cell to grey it out and it greys every 4th or 6th cell instead of only the single cell that was swiped.

The tableview is initialized as follows:

func setupView() {
    view.backgroundColor = .white
    tableView.register(EntityCell.self, forCellReuseIdentifier: "entityCell")
    tableView.separatorStyle = .none
    tableView.dataSource = self
    tableView.delegate = self
}

Here is my query to get the data:

func getEntities(taxId : String) {
    dispatchGroup.enter()
    db.collection("Taxonomy").whereField("entityId", isEqualTo: entityId).whereField("status", isEqualTo: 401).getDocuments { (orderSnapshot, orderError) in
        if orderError != nil {
            self.showError(show: "Error", display: orderError!.localizedDescription)
        } else {
            self.entitiesArray.append(contentsOf: (orderSnapshot?.documents.compactMap({ (orderDocuments) -> Order in
                Order(dictionary: orderDocuments.data(), invoiceId: orderDocuments.documentID, opened: false)!
            }))!)
            self.dispatchGroup.leave()
        }
        DispatchQueue.main.async {
            self.tableView.reloadData()
        }
    }
}

Here are the standard override functions to populate the tableview:

override func numberOfSections(in tableView: UITableView) -> Int {
    return 1
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return entitiesArray.count
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    guard let cell = tableView.dequeueReusableCell(withIdentifier: "entityCell", for: indexPath) as? EntityCell else { return UITableViewCell() }
    let entityRow = entitiesArray[indexPath.row]
    cell.selectionStyle = .none
    cell.setTaxonomy(entity: entityRow) // Setting up the cell with the array values
    return cell
}

Everything is working fine upto this point. And finally here is the override func for swipe action:

override func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
    let complete = UIContextualAction(style: .normal, title: "Verified") { (action, view, completionHandler) in
        self.db.collection("Taxonomy").document(self.entitiesArray[indexPath.row].entityId).updateData(["status": 411]) { (error) in
            if error == nil {
                let cell = tableView.cellForRow(at: indexPath) as? EntityCell
                cell?.changeStatus(currentEntity: self.entitiesArray[indexPath.row])
            }
        }
        completionHandler(true)
    }
    complete.image = UIImage(named: "icon_approved")
    complete.backgroundColor = UIColor(hex: Constants.Colors.secondary)

    let swipe = UISwipeActionsConfiguration(actions: [complete])
    return swipe
}

So I swipe right from the trailing edge of the cell and I see the underlying color and icon as expected. And the cell turns grey via this function via a protocol:

extension EntityCell : EntityStatusDelegate {


    func changeStatus(currentEntity: EntityObject) {
        entityCellBackground.backgroundColor = .systemGray4
    }
}

The cell turns grey. And then I scroll down and I see every 4th or 6th cell is grey as well. Any idea what is going wrong? I am pretty flummoxed at this point.

Upvotes: 0

Views: 117

Answers (1)

Helge Becker
Helge Becker

Reputation: 3243

Cells get recycled. You need either configure them completely or overwrite the prepareForReuse function of the cell or give each cell an unique reuseidentifyer so the tableview can recycle them.

(Last option is the worst as it cost a lot more memory)

Option 1: Just set the backgroundcolor:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    guard let cell = tableView.dequeueReusableCell(withIdentifier: "entityCell", for: indexPath) as? EntityCell else { return UITableViewCell() }
    let entityRow = entitiesArray[indexPath.row]
    cell.selectionStyle = .none
    cell.setTaxonomy(entity: entityRow) // Setting up the cell with the array values
    cell.entityCellBackground.backgroundColor = (whatever the default color is)
    return cell
}

Upvotes: 1

Related Questions