0

I create a custom cell that contains a button, I need to create segue from this button to other VC but first of all, I would like to push an object with that segue.

I already try to use cell.button.tag, but I did not succeed.

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

        if segue.identifier == "showMap" {
            let mapVC = segue.destination as! MapViewController
            //guard let indexPath = tableView.indexPathForSelectedRow else { return }
            mapVC.place = places[] // <- "here I need index of button in cell"
        }
    }
Ben Rockey
  • 920
  • 6
  • 23
  • Possible duplicate of [How to use navigationController.pushViewController in TableCell class?](https://stackoverflow.com/questions/56039560/how-to-use-navigationcontroller-pushviewcontroller-in-tablecell-class) – Mahendra May 22 '19 at 09:03
  • you can use delegate method `didSelectItemAt indexPath` and indexPath of selected cell will be known or use of gesture recognizer instead of a segue. – Volodymyr May 22 '19 at 09:11

3 Answers3

1

Instead of using the segue, handle the navigation programatically through a closure in UITableViewCell.

class CustomCell: UITableViewCell {
    var buttonTapHandler: (()->())?

    @IBAction func onTapButton(_ sender: UIButton) {
        self.buttonTapHandler?()
    }
}

In the above code, I've create a buttonTapHandler - a closure, that will be called whenever the button inside the cell is tapped.

Now, in cellForRowAt method when you dequeue the cell, set the buttonTapHandler of CustomCell.

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell", for: indexPath) as! CustomCell
    cell.buttonTapHandler = {[weak self] in
        if let mapVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "MapViewController") as? MapViewController {
            mapVC.place = places[indexPath.row]
            self?.navigationController?.pushViewController(mapVC, animated: true)
        }
    }
    return cell
}

In the above code, buttonTapHandler when called will push a new instance of MapViewController along with the relevant place based on the indexPath.

PGDev
  • 23,751
  • 6
  • 34
  • 88
0

if you don't want to execute your code in didSelectRowAt method, another good approach in my opinion is to create a delegate of your custom cell. See the code below

// This is my custom cell class
class MyCustomCell: UITableViewCell {

    // The button inside your cell
    @IBOutlet weak var actionButton: UIButton!
    var delegate: MyCustomCellDelegate?

    @IBAction func myDelegateAction(_ sender: UIButton) {
        delegate?.myCustomAction(sender: sender, index: sender.tag)
    }

    // Here you can set the tag value of the button to know
    // which button was tapped
    func configure(index: IndexPath){
       actionButton.tag = index.row
    }

}

protocol MyCustomCellDelegate {
    func myDelegateAction(sender: UIButton, index: Int)
}

Delegate the ViewController where you use your custom cell.

class MyViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
      let cell = tableView.dequeueReusableCell(withIdentifier: "MyCellIdentifier", for: indexPath) as! MyCustomCell

      cell.configure(index: indexPath)
      cell.delegate = self

      return cell
    }
}

And at the end customize your method extending your custom cell delegate

extension MyViewController: MyCustomCellDelegate {

    func myDelegateAction(sender: UIButton, index: Int) {
        // Do your staff here
    }
}

I hope I was helpful.

Alessandro
  • 2,927
  • 1
  • 10
  • 14
0

In the custom cell:

import UIKit

protocol CustomCellDelegate: class {
    func btnPressed(of cell: CustomCell?)
}

class CustomCell: UITableViewCell {

    weak var delegate: CustomCellDelegate?

    @IBAction func btnTapped(_ sender: UIButton) {
        delegate?.btnPressed(of: self)
    }

}

And in the view controller:

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell: CustomCell = tableView.dequeueReusableCell(for: indexPath)
        cell.delegate = self

        return cell
    }

    extension ViewController: CustomCellDelegate {

    func btnPressed(of cell: CustomCell?) {
        if let cell = cell, let indexPath = tableView.indexPath(for: cell) {
            // Your stuff here
        }
    }

}
Sujan
  • 147
  • 1
  • 3