Swift: Passing data between view controllers
Published: 2024-04-18 15:40:10

There are multiple options for passing data between view controllers.

- Using Navigation Controller Push
- Using Segue
- Using Delegate
- Using Notification Observer
- Using Block

**Step 1. Declare variable in ViewControllerB
**
```
var isSomethingEnabled = false

```
**Step 2. Print Variable in ViewControllerB' ViewDidLoad method
**
```

override func viewDidLoad() {
    super.viewDidLoad()
    // Print value received through segue, navigation push
    print("Value of 'isSomethingEnabled' from ViewControllerA: ", isSomethingEnabled)
}
```
**Step 3. In ViewControllerA Pass Data while pushing through Navigation Controller**

```
if let viewControllerB = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "ViewControllerB") as? ViewControllerB {
    viewControllerB.isSomethingEnabled = true
    if let navigator = navigationController {
        navigator.pushViewController(viewControllerB, animated: true)
    }
}
```
So here is the complete code for:

**ViewControllerA**

```

import UIKit

class ViewControllerA: UIViewController  {

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    // MARK: Passing data through navigation PushViewController
    @IBAction func goToViewControllerB(_ sender: Any) {

        if let viewControllerB = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "ViewControllerB") as? ViewControllerB {
            viewControllerB.isSomethingEnabled = true
            if let navigator = navigationController {
                navigator.pushViewController(viewControllerB, animated: true)
            }
        }
    }
}
```
**ViewControllerB
**
```

import UIKit

class ViewControllerB: UIViewController {

    // MARK:  - Variable for Passing Data through Navigation push
    var isSomethingEnabled = false

    override func viewDidLoad() {
        super.viewDidLoad()
        // Print value received through navigation push
        print("Value of 'isSomethingEnabled' from ViewControllerA: ", isSomethingEnabled)
    }
}
```
**Passing Data through Segue**: From ViewControllerA to ViewControllerB

**Step 1. Create Segue from ViewControllerA to ViewControllerB and give Identifier = showDetailSegue in Storyboard as shown below**

**
Step 2. In ViewControllerB Declare a viable named isSomethingEnabled and print its value.**
**
Step 3. In ViewControllerA pass isSomethingEnabled's value while passing Segue**

So here is the complete code for:

**ViewControllerA
**
```
import UIKit

class ViewControllerA: UIViewController  {

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    // MARK:  - - Passing Data through Segue  - -
    @IBAction func goToViewControllerBUsingSegue(_ sender: Any) {
        performSegue(withIdentifier: "showDetailSegue", sender: nil)
    }

    // Segue Delegate Method
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if (segue.identifier == "showDetailSegue") {
            let controller = segue.destination as? ViewControllerB
            controller?.isSomethingEnabled = true//passing data
        }
    }
}
```
**ViewControllerB
**
```
import UIKit

class ViewControllerB: UIViewController {
    var isSomethingEnabled = false

    override func viewDidLoad() {
        super.viewDidLoad()
        // Print value received through segue
        print("Value of 'isSomethingEnabled' from ViewControllerA: ", isSomethingEnabled)
    }
}
```
_Passing Data through Delegate: From ViewControllerB to ViewControllerA_

**Step 1. Declare Protocol ViewControllerBDelegate in the ViewControllerB file, but outside the class**

```

protocol ViewControllerBDelegate: NSObjectProtocol {

    // Classes that adopt this protocol MUST define
    // this method -- and hopefully do something in
    // that definition.
    func addItemViewController(_ controller: ViewControllerB?, didFinishEnteringItem item: String?)
}
```
**Step 2. Declare Delegate variable instance in ViewControllerB
**
```
var delegate: ViewControllerBDelegate?

```
**Step 3. Send data for delegate inside viewDidLoad method of ViewControllerB**

```
delegate?.addItemViewController(self, didFinishEnteringItem: "Data for ViewControllerA")
```
**Step 4. Confirm ViewControllerBDelegate in ViewControllerA
**
```
class ViewControllerA: UIViewController, ViewControllerBDelegate  {
// to do
}
```
**Step 5. Confirm that you will implement a delegate in ViewControllerA**

```
if let viewControllerB = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "ViewControllerB") as? ViewControllerB {
    viewControllerB.delegate = self//confirming delegate
    if let navigator = navigationController {
        navigator.pushViewController(viewControllerB, animated: true)
    }
}
```
**Step 6. Implement delegate method for receiving data in ViewControllerA**

```

func addItemViewController(_ controller: ViewControllerB?, didFinishEnteringItem item: String?) {
    print("Value from ViewControllerB's Delegate", item!)
}
```
So here is the complete code for:

**ViewControllerA
**
```
import UIKit

class ViewControllerA: UIViewController, ViewControllerBDelegate  {

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    // Delegate method
    func addItemViewController(_ controller: ViewControllerB?, didFinishEnteringItem item: String?) {
        print("Value from ViewControllerB's Delegate", item!)
    }

    @IBAction func goToViewControllerForDelegate(_ sender: Any) {

        if let viewControllerB = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "ViewControllerB") as? ViewControllerB {
            viewControllerB.delegate = self
            if let navigator = navigationController {
                navigator.pushViewController(viewControllerB, animated: true)
            }
        }
    }
}
```
**ViewControllerB
**


```
import UIKit
//Protocol decleare
protocol ViewControllerBDelegate: NSObjectProtocol {
    // Classes that adopt this protocol MUST define
    // this method -- and hopefully do something in
    // that definition.
    func addItemViewController(_ controller: ViewControllerB?, didFinishEnteringItem item: String?)
}

class ViewControllerB: UIViewController {
    var delegate: ViewControllerBDelegate?

    override func viewDidLoad() {
        super.viewDidLoad()
        // MARK:  - - - -  Set Data for Passing Data through Delegate  - - - - - -
        delegate?.addItemViewController(self, didFinishEnteringItem: "Data for ViewControllerA")
    }
}
```
_Passing Data through Notification Observer: From ViewControllerB to ViewControllerA_

**Step 1. Set and post data in the notification observer in ViewControllerB**

let objToBeSent = "Test Message from Notification"
        NotificationCenter.default.post(name: Notification.Name("NotificationIdentifier"), object: objToBeSent)
**Step 2. Add Notification Observer in ViewControllerA
**
NotificationCenter.default.addObserver(self, selector: #selector(self.methodOfReceivedNotification(notification:)), name: Notification.Name("NotificationIdentifier"), object: nil)
**Step 3. Receive Notification data value in ViewControllerA
**
```
@objc func methodOfReceivedNotification(notification: Notification) {
    print("Value of notification: ", notification.object ?? "")
}
```
So here is the complete code for:

**ViewControllerA
**
```
import UIKit

class ViewControllerA: UIViewController{

    override func viewDidLoad() {
        super.viewDidLoad()

        // Add observer in controller(s) where you want to receive data
        NotificationCenter.default.addObserver(self, selector: #selector(self.methodOfReceivedNotification(notification:)), name: Notification.Name("NotificationIdentifier"), object: nil)
    }

    // MARK: Method for receiving Data through Post Notification
    @objc func methodOfReceivedNotification(notification: Notification) {
        print("Value of notification: ", notification.object ?? "")
    }
}
```
**ViewControllerB**

```
import UIKit

class ViewControllerB: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // MARK:Set data for Passing Data through Post Notification
        let objToBeSent = "Test Message from Notification"
        NotificationCenter.default.post(name: Notification.Name("NotificationIdentifier"), object: objToBeSent)
    }
}
```

_Passing Data through Block: From ViewControllerB to ViewControllerA
_
**Step 1. Declare block in ViewControllerB
**
```

var authorizationCompletionBlock:((Bool)->())? = {_ in}
```
**Step 2. Set data in block in ViewControllerB
**
```
if authorizationCompletionBlock != nil
{
    authorizationCompletionBlock!(true)
}
```
**Step 3. Receive block data in ViewControllerA**

```
// Receiver Block
controller!.authorizationCompletionBlock = { isGranted in
    print("Data received from Block is: ", isGranted)
}
```


So here is the complete code for:

**ViewControllerA**

```
import UIKit

class ViewControllerA: UIViewController  {

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    // MARK:Method for receiving Data through Block
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if (segue.identifier == "showDetailSegue") {
            let controller = segue.destination as? ViewControllerB
            controller?.isSomethingEnabled = true

            // Receiver Block
            controller!.authorizationCompletionBlock = { isGranted in
                print("Data received from Block is: ", isGranted)
            }
        }
    }
}
```

**ViewControllerB**

```
import UIKit

class ViewControllerB: UIViewController {

    // MARK: Variable for Passing Data through Block
    var authorizationCompletionBlock:((Bool)->())? = {_ in}

    override func viewDidLoad() {
        super.viewDidLoad()

        // MARK: Set data for Passing Data through Block
        if authorizationCompletionBlock != nil
        {
            authorizationCompletionBlock!(true)
        }
    }
}
```