Passing data between View Controllers



When preparing the incoming view controller, we need to first decide how do we want to configure our data passing:

  • using only an action
  • using an action and a segue
  • using only a segue

Assume we have a FirstViewController and we would like it to be able to pass data to a SecondViewController. The first view of the storyboard (connected to FirstViewController) has three buttons (created as @IBOutlet) of which the first two are connected to an action method named sendData(). This means, when we press any of these two buttons, this @IBAction method will execute. The SecondViewController has a property named receivedData (initialized to 2 - we will understand later why) and the second view has a label created as an outlet that we could use to display the passed data, and a button connected to an action method goBack() to go back to the first screen. Here are the two view controllers:

 
class FirstViewController: UIViewController {
    @IBOutlet weak var buttonOne: UIButton!
    @IBOutlet weak var buttonTwo: UIButton!
    @IBOutlet weak var buttonThree: UIButton!
    
    @IBAction func sendData(sender: UIButton) {
    }
}

class SecondViewController: UIViewController {
    @IBOutlet weak var label: UILabel!
    var receivedData = 2

    override func viewDidLoad() {
        super.viewDidLoad()
        label.text = "\(receivedData)"
    }

    @IBAction func goBack(sender: UIButton) {
        self.dismissViewControllerAnimated(true, completion: nil)
    }
}

Now let’s focus on the first button. We want to send some data to the SecondViewController when it’s pressed. For this we need to first give the second view an identifier (Storyboard ID) named SecondViewController (or some other name of your choice) under the Identity Inspector in the storyboard. Now we can instantiate the second view by its identifier like this:

 
@IBAction func sendData(sender: UIButton) {
    if sender == buttonOne {
        let controller = self.storyboard?.instantiateViewControllerWithIdentifier("SecondViewController") as! SecondViewController
        controller.receivedData = 1
        self.presentViewController(controller, animated: true, completion: nil)
    }
}

For the second button we need to create a segue named ButtonTwoSegue that connects the first view to the second view. Now, inside the sendData() method right after the if statement append an else statement where we handle the action for our second button:

 
@IBAction func sendData(sender: UIButton) {
    if sender == buttonOne {
        let controller = self.storyboard?.instantiateViewControllerWithIdentifier("SecondViewController") as! SecondViewController
        controller.receivedData = 1
        self.presentViewController(controller, animated: true, completion: nil)
    }
    else if sender == buttonTwo {
        // notice that we do not change receivedData here - we leave it to its default value of 2

        performSegueWithIdentifier("ButtonTwoSegue", sender: self)
    }
    // else, do nothing else anymore - for the third button we create another method

}

For the third button we need to create another segue named ButtonThreeSegue that connects buttonThree this time (not the first view) to the second view. Now, we override the prepareForSegue() method to pass the data when the third button is pressed:

 
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if segue.identifier == "ButtonThreeSegue" {
        let controller = segue.destinationViewController as! SecondViewController
        controller.receivedData = 3
    }
}

At this point you can run your project and try each of the three buttons to see how the label has a receivedData value of 1, 2 or 3 depending on what button was pressed.

Until next time!