iosswiftuitableviewuikitdidselectrowatindexpath

Swift - Adding target to UIButton in UITableView not working


I have a UITableView, and in each of the UITableViewCells, I have a button, which should perform an action when selected. If the user decides the select the actual cell, I handle another action within the didSelectRowAt function. I am not sure if I am missing something, but my button does not work when selected, but performs the didSelectRowAt function.

The layout and constraints work just fine. It is just not recognizing the tap, and then pushes to the didSelectRowAt

UIViewController Code (Clipped)

class MyProfile: UIViewController, UITableViewDelegate, UITableViewDataSource {
    
    let tableView : UITableView = {
        let tableView = UITableView()
        tableView.translatesAutoresizingMaskIntoConstraints = false
        tableView.separatorStyle = .none
        tableView.backgroundColor = UIColor.white
        return tableView
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.addSubview(tableView)
        tableView.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 10).isActive = true
        tableView.leftAnchor.constraint(equalTo: self.view.leftAnchor).isActive = true
        tableView.rightAnchor.constraint(equalTo: self.view.rightAnchor).isActive = true
        tableView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: 10).isActive = true
        
        view.backgroundColor = UIColor.white
        
        tableView.delegate = self
        tableView.dataSource = self
        tableView.register(ProfileCell.self, forCellReuseIdentifier: "profileCell")

        // data and backend stuff to reload tableview has been removed, so there is not too much code
        // Do any additional setup after loading the view.
    }
    
    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        self.myServices.text = "My Services"
        return myJobs.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "profileCell", for: indexPath) as! ProfileCell
        
        cell.selectionStyle = .none
        
        cell.deleteButton.addTarget(self, action: #selector(deletePostPressed), for: .touchUpInside)
        cell.editButton.addTarget(self, action: #selector(editPostPressed), for: .touchUpInside)
        
        return cell
    }
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        self.navigationController?.pushViewController(ViewPostController(), animated: true)
    }
    
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 175
    }
    
    @objc func deletePostPressed() {
        print("delete")
    }
    
    @objc func editPostPressed() {
        print("edit")
        self.present(Home(), animated: true, completion: nil)
    }

}

UITableViewCell Code (Clipped)

class ProfileCell: UITableViewCell {
    
    let editButton : UIButton = {
        let button = UIButton(type: .system)
        button.setTitle("Edit", for: .normal)
        button.setTitleColor(UIColor.mainBlue, for: .normal)
        button.backgroundColor = UIColor(red: 240/255, green: 240/255, blue: 240/255, alpha: 1)
        button.isUserInteractionEnabled = true
        button.translatesAutoresizingMaskIntoConstraints = false
        button.layer.borderWidth = 1
        button.layer.borderColor = UIColor.mainBlue.cgColor
        return button
    }()
    
    let deleteButton : UIButton = {
        let button = UIButton(type: .system)
        button.setTitle("Delete", for: .normal)
        button.setTitleColor(UIColor.mainBlue, for: .normal)
        button.backgroundColor = UIColor(red: 240/255, green: 240/255, blue: 240/255, alpha: 1)
        button.isUserInteractionEnabled = true
        button.translatesAutoresizingMaskIntoConstraints = false
        button.layer.borderWidth = 1
        button.layer.borderColor = UIColor.mainBlue.cgColor
        return button
    }()
    
    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
        self.selectionStyle = .none
    }
    
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        
        isUserInteractionEnabled = true
        
        addSubview(editButton)
        editButton.layer.cornerRadius = 15
        editButton.layer.masksToBounds = true
        editButton.topAnchor.constraint(equalTo: saleNumber.bottomAnchor, constant: 7).isActive = true
        editButton.rightAnchor.constraint(equalTo: informationView.rightAnchor, constant: -15).isActive = true
        editButton.heightAnchor.constraint(equalToConstant: 30).isActive = true
        editButton.widthAnchor.constraint(equalToConstant: 85).isActive = true

        addSubview(deleteButton)
        deleteButton.layer.cornerRadius = 15
        deleteButton.layer.masksToBounds = true
        deleteButton.topAnchor.constraint(equalTo: saleNumber.bottomAnchor, constant: 7).isActive = true
        deleteButton.rightAnchor.constraint(equalTo: editButton.leftAnchor, constant: -15).isActive = true
        deleteButton.heightAnchor.constraint(equalToConstant: 30).isActive = true
        deleteButton.widthAnchor.constraint(equalToConstant: 85).isActive = true
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

I am not sure what else could be the problem. I have declared delegates, corrected everything, and made sure everything else that needed to be initialized was, and still it doesn't work.


Solution

  • It's a matter of hierarchy, you need to add the buttons to the contentView. If you just add a subview to the view, it goes behind the contentView of the UITableViewCell.

    Visually, where the selected one is the contentView of the cell, you can see that the actual button is behind it: enter image description here

    So contentView.addSubview(editButton) and contentView.addSubview(deleteButton) does the job.