Sharing Data Between Two View Controllers

An iOS app typically displays one view on the screen at a time. That means if you type information in one view, that information will likely get passed on to a second view. The trick is transferring data from one view to another.

The basic process involves knowing that each view (displayed on the storyboard) must be associated with a Swift file called by a generic name such as ViewController.swift. So if you have two views, each view needs its own Swift view controller.

In the first view, you need a text box for the user to enter data in. Then you need an IBOutlet to hold this data like this:

@IBOutlet var textBox: UITextField!

Now you need to transfer this IBOutlet data from the first view to the second one. To do this, you must first define a variable in the second view like this:

var textProperty : String?

This variable in the second view controller can then be displayed in a label on this second view such as:

    var textProperty : String?
    @IBOutlet var displayDataLabel: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        displayDataLabel.text = textProperty

        // Do any additional setup after loading the view.
    }

The above code takes the data stored in the textProperty variable and displays it in the displayDataLabel. Now the big question is how to transfer data from one view to another.

One way to do this is to embed the two views inside a Navigation Controller so it automatically takes care of moving back and forth between the two views. Then we have two options. 

In almost any programming language, you can accomplish tasks in two ways: programmatically or visually. Programmatically means writing code to do everything. Generally this gives you the most control over everything, but also forces you to write a lot of code to perform user interface tasks. As a general rule, you want to write as little code as possible that only focuses on the function of your app since that will let you focus on the core features of your app.

To transfer data programmatically, we must first identify the Swift file, connected to the second view, where we want to send the data. That means creating a constant to represent this second Swift view controller file. Assuming the second view is linked to the View2Controller.swift file, we can declare a constant to represent the View2Controller.swift file like this:

let controller: View2Controller

Now we can store the second view in this constant like this:

controller = storyboard?.instantiateViewController(withIdentifier: "View2") as! View2Controller

To make the above code work, it needs to know the view to use. That means this second view needs a Storyboard ID of “View2” that you can define by clicking on the second view, opening the Identity Inspector, and typing “View2” into the Storyboard ID text field like this:

Now we can retrieve data from the first view and transfer it to the second view’s textProperty variable like this:

        if (textBox.text?.isEmpty)! {
            controller.textProperty = "Empty text field"
        } else {
            controller.textProperty = self.textBox.text!
        }

This if-else statement simply sends a default string (“Empty text field” into the second view’s textProperty if the user did not type anything into the text box on the first view. Otherwise, it takes this text box data and transfers it into the textProperty variable of the second view.

Now we need to display this second view using code like this:

self.navigationController?.pushViewController(controller, animated: true)

This pushes the second view into the navigation controller, which conveniently displays a Back link to go back to the first view. So the user can type data into a text box and click a button to transfer data from the text box into the second view. The entire code for this button’s IBAction looks like this:

    @IBAction func codeOnly(_ sender: UIButton) {
        let controller: View2Controller
        controller = storyboard?.instantiateViewController(withIdentifier: "View2") as! View2Controller
        
        if (textBox.text?.isEmpty)! {
            controller.textProperty = "Empty text field"
        } else {
            controller.textProperty = self.textBox.text!
        }
        
        self.navigationController?.pushViewController(controller, animated: true)
    }

Now doing everything programmatically can be cumbersome, so Xcode offers a simpler way. First, you need to Control-drag from a button on the first view to the second view. This creates a segue that links the two views together.

Now you just have to write a prepare for sequence function that involves two steps. First, we need to create a constant to represent the second view’s Swift file (View2Controller.swift). Second, we need to transfer the data to the second view’s textProperty like this:

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        // Control-drag from button to view
        
        let controller = segue.destination as! View2Controller
        if (textBox.text?.isEmpty)! {
            controller.textProperty = "Empty text field"
        } else {
            controller.textProperty = self.textBox.text!
        }
    }

Notice that using a segue eliminates the need to write code to instantiate the second view or push the second view on the screen since the segue and navigation controller takes care of moving to the second view. The trick is that for the above code to work, you must create a segue between a button (on the first view) that points to the second view. The entire code for the first view’s Swift file (ViewController.swift) looks like this:

import UIKit

class ViewController: UIViewController {

    @IBOutlet var textBox: UITextField!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    @IBAction func codeOnly(_ sender: UIButton) {
        let controller: View2Controller
        controller = storyboard?.instantiateViewController(withIdentifier: "View2") as! View2Controller
        
        if (textBox.text?.isEmpty)! {
            controller.textProperty = "Empty text field"
        } else {
            controller.textProperty = self.textBox.text!
        }
        
        self.navigationController?.pushViewController(controller, animated: true)
    }
    

    
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        // Control-drag from button to view
        
        let controller = segue.destination as! View2Controller
        if (textBox.text?.isEmpty)! {
            controller.textProperty = "Empty text field"
        } else {
            controller.textProperty = self.textBox.text!
        }
    }
}

The complete code for the second view’s Swift file (View2Controller.swift) looks like this:

import UIKit

class View2Controller: UIViewController {

    var textProperty : String?
    @IBOutlet var displayDataLabel: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        displayDataLabel.text = textProperty

        // Do any additional setup after loading the view.
    }
}

When you run this project, you’ll see two buttons. The top button transfers data to the second view programmatically. The bottom bottom transfers data to the second view using a segue and the prepare for segue function. 

You can choose whichever method you like to transfer data from one view to another, but it’s best to be consistent. In general, it’s probably best to write as little code as possible.

December 15th, 2018 by
HTML Snippets Powered By : XYZScripts.com