Search code examples
iosswiftoverridingsegueindexpath

How to get selected table view cell row in segue?


I am developing an iOS app using Swift and I have a view controller that segues from a table view cell content view by selecting a cell row or selecting a button inside of that cell row's content view. The original view controller that contains the table view performs a segue on two different occasions: one segue when the cell row itself is selected (segues to an avplayerviewcontroller and plays a video depending on the cell row that was selected) and the second segue happens when you press a button that is inside of the content view of the table view cell. In the first segue, I am able to pass the the cell row that is selected with if let indexPath = self.tableview.indexPathForSelectedRow when I override the first segue. However when I try to pass the cell row that was selected when I try to override the second segue that happens when you press the button it doesn't work. Is this because the button inside of the table view cell doesn't know which row it was selected in? If so, how can I solve this problem, and if not what is a viable solution to solve such issue? Reminder: The "playDrill" segue is trigged when you select a cell row, the "Tips" segue is trigged when you selected a button inside of that same cell row's content view

Code for first segue that happens when you select a cell row (this segue functions as desired):

class DrillsViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

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

    if segue.identifier == "playDrill" {
        if let indexPath = self.tableView.indexPathForSelectedRow {
            if initialRow == 1 {
                drillVid = videoURL[indexPath.row]
                playerViewController = segue.destination as! PlayerController
                playerViewController.player = AVPlayer(playerItem: AVPlayerItem(url: drillVid))
                playerViewController.player?.play()
                print(indexPath) //prints correct value which is "[0,6]"
            }
            if initialRow == 3 {
                drillVid = videoUrl[indexPath.row]
                playerViewController = segue.destination as! PlayerController
                playerViewController.player = AVPlayer(playerItem: AVPlayerItem(url: drillVid))
                playerViewController.player?.play()
            }

Code for second segue that triggers when you select a button inside of the cell's content view (I want this segue to have the value of indexPath as in the first segue, but when I try to use that code it doesn't return the correct value):

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

    if segue.identifier == "Tips" {
       if let indexPath = self.tableview.indexPathForSelectedRow {
        if initialRow == 1 {
            print(indexPath)  //the value printed is "6", I want "[0,6]" like the first code block
            let tipVC = segue.destination as! KeysController

            } 
        }
    }
}

Solution

  • You are not able to get the selected index of the selected cell because you are not actually selecting a cell. You are pressing a button inside the cell.

    So, what you do is get a reference to the button, get the button's superview (the cell) and then you can get the indexPath of that cell.

    class TableViewController: UITableViewController {
    
        var indexPathForButton: IndexPath?
    
        @IBAction func buttonPressed(_ sender: UIButton) {
    
            let button = sender
            let cell = button.superview!.superview! as! MyCell  // The number of levels deep for superviews depends on whether the button is directly inside the cell or in a view in the cell
            indexPathForButton = tableView.indexPath(for: cell)
        }
    

    Then in prepare(for segue:)

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    
        if segue.identifier == "Tips" {
            if initialRow == 1 {
              print(indexPathForButton)
              let tipVC = segue.destination as! KeysController
            }
        }
     }