Segue not getting selected row number

16,080

Solution 1

The best way to do this kind of thing is not to use the delegate.

Updated Swift 4+

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    let selectedIndex = tableView.indexPath(for: sender as! UITableViewCell)
    // Do your stuff with selectedIndex.row as the index
}

Original Answer

override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
    let selectedIndex = self.tableView.indexPathForCell(sender as UITableViewCell)
    // Do your stuff with selectedIndex.row as the index
}

Solution 2

Swift 3 update:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    let selectedIndex = tableView.indexPath(for: sender as! UITableViewCell)!
    // Do your actual preparing here...
}
Share:
16,080
Shades
Author by

Shades

Amateur, hobbyist programmer. I make structural Perl scripts which are useful only to me. I also make bad, object oriented iOS apps which are not useful to anyone.

Updated on June 15, 2022

Comments

  • Shades
    Shades almost 2 years

    I am passing data from a table view controller to a detail view. I tried using indexPath.row directly in my prepareForSegue method, however it displays an error of

    use of unresolved identifier 'indexPath'

    So, after searching the web, I set up the variable indexOfSelectedPerson which is assigned the value of indexPath.row. The problem when I run the app in the simulator is that prepareForSegue is getting the initial value of indexOfSelectedPerson (0), then getting the value of the selected row only after I click it. So, when I hit the back button in the Simulator and select a different row, the detail view shows the info of the row I selected the previous time.

    import UIKit
    
    class MasterTableViewController: UITableViewController {
    
        var people = []
        var indexOfSelectedPerson = 0
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            people = ["Bob", "Doug", "Jill"]
        }
    
        override func numberOfSectionsInTableView(tableView: UITableView?) -> Int {
           return 1
        }
    
        override func tableView(tableView: UITableView?, numberOfRowsInSection section: Int) -> Int {
            return people.count
        }
    
        override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
    
            let cell = tableView!.dequeueReusableCellWithIdentifier("personCell", forIndexPath: indexPath) as UITableViewCell
    
            cell.text = "\(people[indexPath.row])"
    
            return cell
        }
    
        override func tableView(tableView: UITableView!, didSelectRowAtIndexPath indexPath: NSIndexPath!)
        {
            indexOfSelectedPerson = indexPath.row
        }
    
    
        override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
    
            if let mySegue = segue.identifier {
    
                if mySegue == "personDetails" {
    
                    let detailsVC: DetailTableViewController = segue.destinationViewController as DetailTableViewController
    
                    detailsVC.selectedPersonName = "\(people[indexOfSelectedPerson])"
                }
            }
        }
    }
    

    So, selecting Doug when the app first starts in the simulator displays the details for Bob because indexPathOfSelectedPerson is 0. Hitting the back button and then selecting Jill displays the details for Doug because indexPathOfSelectedPerson became 1 when I clicked on Doug the previous time. I'm guessing the problem stems from the order in which the methods are called.

  • Shades
    Shades almost 10 years
    Your added line gave an error in Xcode regarding downcasting AnyObject and suggested changing the line to: let selectedIndex = self.tableView.indexPathForCell(sender as UITableViewCell). That fixed the error. I changed indexOfSelectedPerson to selectedIndex.row as you said and everything works. Thank you.
  • Andrew Bennet
    Andrew Bennet about 8 years
    Just what I was looking for. In Xcode 7 (Swift 2.2), you need to force cast the sender to a UITableViewCell like so: self.tableView.indexPathForCell(sender as! UITableViewCell)
  • Pintu Rajput
    Pintu Rajput almost 7 years
    if I have a different types of custom class cells Then how can I detect type of cell. Thanks