Search code examples
iosswiftuitableviewuisearchcontroller

Get the indexpath from custom button in accessoryView of a UITableViewCell


I have a UISearchController with a separate UITableViewController as its searchResultsController.

class SearchResultsViewController: UITableViewController {

    var fruits: [String] = []

    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.tableFooterView = UIView(frame: .zero)
        tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
    }

    @objc func addFruit(_ sender: UIButton) {
        let point = tableView.convert(sender.bounds.origin, to: sender)
        let indexPath = tableView.indexPathForRow(at: point)
        print(indexPath?.row)
    }

    // MARK: - Table view data source
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return fruits.count
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
        cell.textLabel?.text = fruits[indexPath.row]
        cell.selectionStyle = .none

        let addButton = UIButton(type: .custom)
        addButton.frame = CGRect(x: 0, y: 0, width: 44, height: 44)
        addButton.setImage(UIImage(named: "add"), for: .normal)
        addButton.contentMode = .scaleAspectFit
        addButton.addTarget(self, action: #selector(addFruit(_:)), for: .touchUpInside)
        addButton.sizeToFit()
        cell.accessoryView =  addButton

        return cell
    }

}

I need to show a custom button in cells that search results are shown. So I added a UIButton as the cells' accessoryView. And it looks and works fine.

enter image description here

Now I need to get the cell's indexPath when the user taps on this button.

I'm trying to get it like shown below.

@objc func addFruit(_ sender: UIButton) {
    let point = tableView.convert(sender.bounds.origin, to: sender)
    let indexPath = tableView.indexPathForRow(at: point)
}

But it keeps returning nil for every cell.

Is there any other way to get the indexPath from a custom button tap? I added a demo project here as well.


Solution

  • Create a custom class named SOButton and add variable of type IndexPath to it. Use this class for your add button initialisation.

    //Your class will look like - 
    
    class SOButton: UIButton {
       var indexPath: IndexPath?
    }
    
    //Your action will look like -
    
    @objc func addFruit(_ sender: SOButton) {
         print(sender?.indexPath.row)
    }
    
    //And in your cellForRow add
    
    let addButton = SOButton(type: .custom)
    addButton.indexPath = indexPath
    

    Hope this helps you :)