Xcode 8/Swift 3: how to make ViewController save state when segue occurs?

how to pass data from second view controller to first view controller in swift
pass data between view controllers swift without segue
swift segue programmatically
segue to another view controller programmatically
unwind segue (swift)
swift modal segue
swift passing data between view controllers programmatically

App has two View Controllers: ViewController (this is the main View Controller that displays the majority of the app's content) and SecondViewController (accessible via a UIButton on ViewController; SecondViewController is only used to display a user's inventory, and a UIButton within SecondViewController allows the user to return to the original view, ViewController). Currently, the app uses the "Show" action segue to switch between View Controllers when the user presses the appropriate UIButton. However, after switching from ViewController to SecondViewController, and then pressing the UIButton to return to ViewController, the properties of ViewController have been reverted to the properties that occur when the app launches (background color is changed, certain text fields appear that shouldn't).

So, how do I "save the state" of ViewController when the user moves to SecondViewController, so that the user resumes where they left off when they return to ViewController?

What you are looking for is an unwind segue. Here's the simplest way of how to create it:

  1. In your ViewController (or, basically any other view controller you are willing to pop to) create an IBAction that accepts an instance of a segue (function name doesn't really matter):

    @IBAction func unwindToThisVC(segue: UIStoryboardSegue) { }

  2. In the storyboard, go to SecondViewController, and control + drag from your UIButton to the Exit outlet of ViewController and then select the IBAction you've created in step 1:

More on Unwind Segues

View Controller Programming Guide for iOS: Using Segues, must be a view or object with a defined action, such as a control, bar button item, or gesture recognizer. Conclusion. Screenshots taken from Xcode 6.1.1.. Segues are a very important part of using Storyboards in Xcode. We can go over the different types of segues another time, but this one shows you how to use the “Show” segue, as well as how to pass data between the two view controllers to customize the second one with whatever custom data is required.

The way you are doing it now (using Show from the second to get back to the first) actually brings up a third VC.

What you want to do is dismiss the second view controller.

The normal way is to implement a protocol for the second one that the first one implements and then to have a function in that protocol for the second one to let the first one know it is done.

When the function is called, the first one dismisses the second and then it will be shown again with its state intact.

Segue between Swift View Controllers, Most apps have more than one view to show during its use. 3, 2019. Xcode 11.2 Swift 5.1.2 On our initial View Controller let's drag out 2 buttons. It will then ask you where to save this, so choose wherever you want. 3. 4. 5. 6. 7. 8. override func prepareForSegue(segue: UIStoryboardSegue, sender:  In this case, we are about to create a segue from the View Controller scene (orange background) to the Second View Controller scene (green background). Once again, open the Main.storyboard file. To easily create the new segue, expand the Document Outline if it’s hidden and select the View Controller object in the View Controller Scene section:

Here is a simple example of segue and unwind that you can adapt to your problem... Assume that you have ViewController with label and a button and a SecondViewController with label and a button.

For the first ViewController...

import UIKit

//steps to receive data back from SecondViewController...
//1. create protocol in the SecondViewController (see SecondViewController code)
//2. conform to the protocol

class ViewController: UIViewController, UnwindSegue {

    //3. method that gets triggred.
    func dataReceived(dataSegued: String) {
        labelOne.text = dataSegued

    @IBOutlet weak var textField: UITextField!
    @IBOutlet weak var labelOne: UILabel!

    var textReceived : String = ""

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


    @IBAction func btPressed(_ sender: Any) {
        performSegue(withIdentifier: "goToSecondController", sender: self)


    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "goToSecondController" {

            let destinationVC = segue.destination as! SecondViewController
            destinationVC.textSegued = textField.text!

            //4. create delegate in the SecondViewController (see SecondViewController code)
            //5. set ourselves up as delegate of SecondViewController
            destinationVC.delegate = self

            //6. then dismiss the SecondViewController (see SecondViewController code)


Then for your SecondViewController...

import UIKit

//1. create protocols and delegates to transfer data back
protocol UnwindSegue {
    //single required method with a single parameter
    func dataReceived(data:String)


class SecondViewController: UIViewController {

    var textSegued : String?

    //4. create delegate of the protocol of type CanReceive that can be a nil. If it is nil, it doesn't go anywhere when BT is pressed
    var delegate : UnwindSegue?

    @IBOutlet weak var label: UILabel!
    @IBOutlet weak var secondTextField: UITextField!

    override func viewDidLoad() {

        // Do any additional setup after loading the view.
        label.text = textSegued

    @IBAction func btTwoPressed(_ sender: Any) {

        //this is not triggered if var delegate is nil (as defined as optional)
        delegate?.dataReceived(data: secondTextField.text!)

        //6. dismiss the 2nd VC so you can see the fist VC
        dismiss(animated: true, completion: nil)



UIViewController, You rarely create instances of the UIViewController class directly. You also specify the relationships and segues between your view controllers, which states for a view controller's views and the state transitions that can occur. As of iOS 8, all rotation-related methods are deprecated. Supporting Swift Playgrounds. 3 3 Component Dynamic Multi UIPickerView Swift Aug 13 '18 2 fit_generator() doesn't works in Spyder Feb 8 '19 0 Xcode 8/Swift 3: how to make ViewController save state when segue occurs?

Passing Data Between View Controllers in iOS: The Definitive Guide, This can happen through a segue or programmatically. Moreover, some view controller containers can make things more complicated. That view controller can then make all the updates it needs to the state of the app. When the user goes back to the previous view controller, this can read the new state in its viewWillAppear (_:) method, as we saw in the example above. Passing data back using a delegate. Sometimes the techniques we have seen are still not enough.

The Right Way to Share State Between Swift View Controllers, State propagation across view controllers is vital in any iOS app. You just have to add a static variable to a class to keep a shared 3. class Singleton {. static let shared = Singleton(). } update the view controller's UI each time it appears on the screen. if let editViewController = segue.destination as? Presenting a View Controller Using Custom Animations. To present a view controller using custom animations, do the following in an action method of your existing view controllers: Create the view controller that you want to present. Create your custom transitioning delegate object and assign it to the view controller’s transitioningDelegate

Understanding the 'sender' in segues and use it to pass on data to , The prepareForSegue(_:sender:) method is the right place to do this. How can we avoid adding extra state variables in our source view controller just for This might happen when no direct user interaction should trigger the action of some 3 distinct segues from the buttons directly to the destination view controller, we  When an iPad or iPhone 6 Plus device is in portrait mode, however, the Split View Controller hides the master panel so that the detail panel is able to utilize the entire screen. In this instance, the master panel is provided in the form of a full screen table view which segues to the detail view when items are selected from the list.