prepareForSegue and PerformSegueWithIdentifier sender

36,912

Solution 1

There are, effectively, two ways you can trigger a segue. The first is via an action on a UI element in Interface Builder, the second is using performSegueWithIdentifier:sender: in your code. I say 'effectively', because under the covers, when the scene is loaded from the storyboard, an action handler is configured that ultimately calls performSegueWithIdentifier:sender:

When performSegueWithIdentifier:sender: is called, the segue object is delivered to your view controller's prepareForSegue:sender: function.

In the case where the segue was initiated by an action on a UI element then the sender will be that UI element (i.e. if it is an action connection on a UIButton then the sender will be the UIButton instance).

If the segue is initiated by your code calling performSegueWithIdentifier:sender: then the sender will be whatever object you passed as the sender. This could be your view controller, a button, an array, anything. So yes, if you pass "Hello World" to performSegueWithIdentifier:sender: as the sender value then this will be the sender in prepareForSegue:sender:

In terms of the order of operations:

  1. performSegueWithIdentifier:sender is called, either by your code or as a result of an action on a UI element
  2. If your view controller implements shouldPerformSegueWithIdentifier:sender: then this function is called. If this function returns false then the segue is cancelled
  3. The segue object and destination view controller object are created
  4. If your view controller implements prepareForSegue:sender: then this function is called.
  5. Once prepareForSegue:sender: returns, the segue completes.

Solution 2

The performSegue method calls a segue to be performed from one view to another. Before the segue actually takes place, the prepareForSegue method is called, and if you want to pass data between the views, you'd do it there.

The performSegue method doesn't take the parameter you want to send. It's only used to call the segue in the first place. Any data that you want to send will be done through prepareForSegue.

Here's an example.

override func viewDidLoad() {
    super.viewDidLoad()

    // Do any additional setup after loading the view.

    performSegueWithIdentifier("test", sender: self)
    //You can set the identifier in the storyboard, by clicking on the segue
}

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if segue.identifier == "test"{
        var vc = segue.destinationViewController as! RandomViewController
        vc.data = "Data you want to pass"
        //Data has to be a variable name in your RandomViewController
    }
}

Let me know if this helps!

Solution 3

The_Curry_Man's answer worked for me. Here's an update of his code for Swift 3.

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.

    performSegue(withIdentifier: "test", sender: self)
    //You can set the identifier in the storyboard, by clicking on the segue
}

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "test"{
        var vc = segue.destinationViewController as! RandomViewController
        vc.data = "Data you want to pass"
        //Data has to be a variable name in your RandomViewController
    }
}

Solution 4

my two cents for beginners... In swift 3 is:

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

}

So, if arriving controller (of class MyController) implements a "fillData" method:

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

    if let destController = segue.destination as MyController{

        destController.fillData(...)
    }

}
Share:
36,912
JasonP
Author by

JasonP

Updated on August 24, 2020

Comments

  • JasonP
    JasonP over 3 years

    I am wondering about how the functions in the title work and also about the sender parameter.

    Lets say a button click calls the performSegue method, does that also call the prepareSegue method as well? Is the prepareSegue method called before the performSegue method but after the button is pressed?

    Also, is the "sender" parameter in both of the functions linked? If I pass in a string as the sender in the performSegue method, will that transfer over to the sender parameter in the prepareSegue method? In other words, if I set the sender parameter in the performSegue method as "Hi world", will the sender parameter in the prepareSegue method also be the same string?

    Thanks

  • Paulw11
    Paulw11 almost 8 years
    You could pass the data you want to send as sender in performSegueWithIdentifier:sender: but you would need to transfer it to the destination view controller in prepareForSegue:sender:
  • MandisaW
    MandisaW over 6 years
    Thanks for this, it saved me a little backtracking - I needed to know if prepareForSegue would still be called independently of checking the return value of shouldPerformSegue.
  • barrylachapelle
    barrylachapelle over 5 years
    Beautiful. Thanks.
  • malhal
    malhal over 5 years
    In UIKit sender is usually either a view or a view controller, because it is used by internal mechanisms used by segues like targetViewControllerForAction:sender: and canPerformAction:sender: if you use a custom object as a sender then it'll mess that up.
  • Paulw11
    Paulw11 over 5 years
    The documentation states no such restriction, and targetViewControllerForAction:Sender and canPerformAction:sender are not invoked when processing performSegueWithIdentifier:sender.
  • malhal
    malhal over 5 years
    For the built in show and show detail storyboard segue templates they are. See from 31mins in this WWDC video developer.apple.com/videos/play/wwdc2014/216 or this link optshiftk.com/2014/08/…
  • malhal
    malhal over 5 years
    UISplitViewController's showViewController uses an internal method _childContainingSender where the sender must be a UIView or UIViewController so it can use a method _isMemberOfViewControllerHierarchy: which is part of its adaptivity.
  • Adam Ri
    Adam Ri over 5 years
    Tried that, does not work. Getting nil in second ViewController. do not know why.
  • malhal
    malhal over 5 years
    The sender param should not be used as a hack to pass data. It needs to be a UIView or similar for the segue to work correctly. Use a property on the view controller for the data to use in prepare.
  • malhal
    malhal over 5 years
    It's a hack to use the sender param for data. Do it the proper way and use a property on the view controller. Even better set it the property in shouldPerformSegue only if it passes validation, then use it in prepare.
  • swiftBoy
    swiftBoy over 4 years
    with Swift 5 performSegue(withIdentifier: "showPartListViewController", sender: self)