To access Tableview cell in Button action

Viewed 1431

I want to delete tableview cell by clicking a button present in the same cell. But I am unable to access the cell in the button action function. Please help me to Access this cell. My code is -

class MatchesViewController: UIViewController{

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    guard let cell = tableView.dequeueReusableCell(withIdentifier: "MatchingUsersTVCell") as? MatchingUsersTVCell else{
        return UITableViewCell()
    }
    let likeUid = userIdArray[indexPath.row]

    cell.heartBtn.tag = indexPath.row

    cell.heartBtn.addTarget(self, action: #selector(userLikeButtonWasTappaed(sender:)), for: .touchUpInside)
    }

    @objc func userLikeButtonWasTappaed(sender: UIButton){
        if let cell = sender.superview as? MatchingUsersTVCell{
            CellAnimator.animate(cell: cell)
        }
        let tag = sender.tag
        let userid = userIdArray[tag]
    }
}
4 Answers

Try this code:

@objc func userLikeButtonWasTappaed(sender: UIButton){

    guard let indexPath = tableView.indexPathForRow(at: sender.convert(sender.frame.origin, to: tableView)) else {
        return
    }

    let cell = tableView.cellForRow(at: indexPath) as? MatchingUsersTVCell
}

And in your cellForRowAt function add the following code:

cell.yourBtn.tag = indexPath.row

        cell.yourBtn.addTarget(self, action: #selector(userLikeButtonWasTappaed(sender:)), for: .touchUpInside)

Within MatchingUsersTVCell, add two properties, one named parentVC of type UIViewController and one named index of type Int:

class MatchingUsersTVCell: UITableViewCell {
    var parentVC: UIViewController!
    var index: Int!

    ...

}

Then, when creating each cell, set these two values appropriately:

class MatchesViewController: UIViewController, UITableViewDelegate, UITableViewDatasource {

    ...

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        guard let cell = tableView.dequeueReusableCell(withIdentifier: "MatchingUsersTVCell") as? MatchingUsersTVCell else {
            return UITableViewCell()
        }
        cell.parentVC = self
        cell.index = index

        ...

        return cell
    }
}

Now, you simply update your parentVC's tableView's data source and reload its data whenever the button is tapped:

class MatchingUsersTVCell: UITableViewCell {

    ...

    @objc func userLikeButtonWasTappaed(sender: UIButton){
        parentVC.userIdArray.remove(at: index)
        parentVC.tableView.reloadData()
    }

}

I'd stay away from using tags, and instead implement protocol/delegate. Using indexPath allows use of multiple sections, etc...

1) Create a protocol:

protocol MatchingUsersTVCellDelegate : class {
    func didTapLikeButton(_ indexPath: IndexPath)
    func didTapOtherButton(_ indexPath: IndexPath)
}

2) Create/Update your cell:

class MatchingUsersTVCell : UITableViewCell {
    weak var delegate: MatchingUsersTVCellDelegate?   
    var indexPath: IndexPath!
    // add target to your like button
    func didTapLIkeButton(_ sender: UIButton) {
        self.delegate?.didTapLikeButton(indexPath)
    }
    func didTapOtherButton() {
        self.delegate?.didTapOtherButton(indexPath)
    }
}

3) make sure your viewController conforms to the new delegate:

extension YourViewController: MatchingUsersTVCellDelegate {
    func didTapLikeButton(_ indexPath: IndexPath) {
        //Do something with the indexPath or indexPath.row
        dataSource.remove(at: indexPath.row)
    }
    func didTapOtherButton(_ indexPath: IndexPath) {
        //Do something else with the indexPath or indexPath.row
    }
}

4) Set delegate and indexPath

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell...
    cell.delegate = self
    cell.indexPath = indexPath
    return cell
}

you can get it like this in your selector method

@objc func userLikeButtonWasTappaed(button:UIButton){
guard let indexPath = myTableView.indexPathForRow(at: button.convertPoint(button.frame.origin, toView: myTableView)) else {
    print("Error: indexPath)")
    return
}

print("indexPath.row: \(indexPath.row)")
}
Related