Delete multiple cells from tableView without conflict

Viewed 167

I have a tableView where the user can tap on a button inside the cell to delete it. That button is connected with this delegate-function:

extension WishlistViewController: DeleteWishDelegate {
    func deleteWish(_ idx: IndexPath){
        // remove the wish from the user's currently selected wishlist
        wishList.wishes.remove(at: idx.row)
        // set the updated data as the data for the table view
        theTableView.wishData.remove(at: idx.row)
        self.theTableView.tableView.deleteRows(at: [idx], with: .right)
        print("deleted")
    }
}

Here is how I call the callback (after an animation is finished):

@objc func checkButtonTapped(){ 
    self.successAnimation.isHidden = false
    self.successAnimation.play { (completion) in
        if completion {
            self.deleteWishCallback?()
        }
    }
}

And this callback is handled in cellForRowAt and passes the indexPath:

cell.deleteWishCallback = {
    self.deleteWishDelegate?.deleteWish(indexPath)
}

It works fine until the user clicks multiple buttons right after another as I get a IndexOutOfBounds-Error. What I was thinking of is to store all the incoming indexes in some sort of list and delete them one after another but each index changes as soon as another cell below itself is deleted. What is the best way to get this done?

2 Answers

How are you sending the indexPath to delete in the delegate, can you show code? You might have retain cycle on your deleted cell, and the index is not valid.

Edit: Solution

You must pass the cell in your closure self.deleteWishCallback?(cell) and then get the actual index path like this

cell.deleteWishCallback = { deletedCell in
 let indexPath = tableView.indexPath(for: deletedCell)
 wishList.wishes.remove(at: indexPath.row)
 tableView.deleteRows(at: [indexPath], with: .right)
 self.deleteWishDelegate?.deleteWish(indexPath)
}

Instead of self.theTableView.tableView.deleteRows(at: [idx], with: .right) just simply reloadData. (self.theTableView.reloadData()) If you set the new datasource for your tableView, you should reload cells.

Related