Search code examples
iosswiftuitableviewsegue

Push segue from Cell doesn't work after click


I have been reading around on various ways to perform segues. I want a push segue from a cell click. I have the segue in the storyboard, so I am not using the didSelectForRow function:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        guard let selectedRow = self.tableView.indexPathForSelectedRow as? Int else { return }

        if segue.identifier == "detail", let vc = segue.destination as? DetailViewController {
            vc.playerImage = UIImageView(image: UIImage(named: "userIcon"))
            vc.currentRankingLabel.text = String(players[selectedRow].ranking)
            vc.scoreLabel.text = String("\(players[selectedRow].wins) - \(players[selectedRow].losses)")
        }
    }

This is what I have got at the moment. It compiles, but the cell will not react to the click!


Solution

  • indexPathForSelectedRow is never Int, it's IndexPath?. Delete the conditional downcast and get the row from its row property

    guard let selectedPath = self.tableView.indexPathForSelectedRow else { return }
    let selectedRow = selectedPath.row
    
    if segue.identifier == "detail", let vc = segue.destination as? DetailViewController {
            vc.playerImage = UIImageView(image: UIImage(named: "userIcon"))
            vc.currentRankingLabel.text = String(players[selectedRow].ranking)
            vc.scoreLabel.text = String("\(players[selectedRow].wins) - \(players[selectedRow].losses)")
        }
    

    However if the segue is connected to the cell I recommend to use the sender parameter which represents the cell

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    
         if segue.identifier == "detail", let vc = segue.destination as? DetailViewController {
            let selectedPath = self.tableView.indexPath(for: sender as! UITableViewCell)!
            let selectedRow = selectedPath.row
            vc.playerImage = UIImageView(image: UIImage(named: "userIcon"))
            vc.currentRankingLabel.text = String(players[selectedRow].ranking)
            vc.scoreLabel.text = String("\(players[selectedRow].wins) - \(players[selectedRow].losses)")
         }
    }
    

    Important note:

    Be aware that the outlets in the destination controller are not connected in prepare(for so nothing will be displayed or the code even crashes.