0

I am trying to send a link over another view when a select a row in UITableView. When I select the row I can see the link is printed however, the value does not get to the function prepareForSegue. It seems like the prepareForSegue function is called before the selection row in UITableView.

var videouserPath = ""

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

        videouserPath =  self.arrayUserVideo[indexPath.row][4]
        print("tableview: ----\(videouserPath)")
    }


    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        print("segue: ----\(videouserPath)")
        if segue.identifier == "toUserVideo"

        {
            if let destinationVC = segue.destinationViewController as? GetVideo_ViewController{

                destinationVC.videoToDisplay = videouserPath
            }
        }
    }

I got in debug:

segue: ----

tableview: ----https://example.com/resources/1361929513_02-02-2016_125830.mov

Why is the segue function called before selection?

SNos
  • 3,430
  • 5
  • 42
  • 92
  • Maybe by setting the segue in the Storyboard from your `UIViewController` rather from the `UITableViewCell` to `GetVideo_ViewController`? – Larme Feb 02 '16 at 15:35

1 Answers1

1

When linking UIStoryboardSegue to UITableViewCell from the storyboard, the messaging is in the order prepareForSegue, didSelectRowAtIndexPath.

Automatic Method

Bypass didSelectRowAtIndexPath altogether.

For general purpose and single selection cells, you do not need to implement didSelectRowAtIndexPath. Let the segue associated with UITAbleViewCell do the work, and handle selection like so:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if segue.identifier == "detailSegueIdentifier" {
        if let indexPath = tableView.indexPathForSelectedRow {
            print(indexPath)
        }
    }
}

Manual Method

If you absolutely need to do extra work before the segue, do not associate it to the UITableViewCell but to the UITableViewController. You will then need to trigger it programmatically. Inspiration here.
In IB, assign the segue to table view controller, give it an identifier (say detailSegueIdentifier), and invoke it like so.

    override func tableView(tableView: UITableView,
                            didSelectRowAtIndexPath indexPath: NSIndexPath) {
        print("didSelectRowAtIndexPath")
        self.performSegueWithIdentifier("detailSegueIdentifier", sender: nil)
    }

Passing parameters to the segue:

Invoking performSegueWithIdentifier will also give you a chance to explicitly pass parameters, not second-guess indexPathForSelectedRow, and not rely on a global(*).

override func tableView(tableView: UITableView,
                        didSelectRowAtIndexPath indexPath: NSIndexPath) {
    print("didSelectRowAtIndexPath")
    self.performSegueWithIdentifier("detailSegueIdentifier", sender: indexPath)
}

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if segue.identifier == "detailSegueIdentifier" {
        if let indexPath = sender as? NSIndexPath {
            let name = db[indexPath.row].key
            if let controller = segue.destinationViewController as? DetailViewController {
                controller.name = name
            }
        }
    }
}

(*) Don't ever rely on globals if you can help it.

Community
  • 1
  • 1
SwiftArchitect
  • 47,376
  • 28
  • 140
  • 179