Apr 09, 2024 iOS

How to Pass data between view controllers

Passing data between view controllers is a common task in iOS development. There are several ways to achieve this:

1.Using Segues: If you’re transitioning between view controllers using segues in Interface Builder, you can override the prepare(for:sender:) method in the source view controller to pass data to the destination view controller before the segue occurs.

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "YourSegueIdentifier" {
        if let destinationVC = segue.destination as? DestinationViewController {
            destinationVC.data = // Your data to pass
        }
    }
}

2.Using Properties: You can create a property in the destination view controller and set its value directly before presenting or pushing the destination view controller.

let destinationVC = DestinationViewController()
destinationVC.data = // Your data to pass
navigationController?.pushViewController(destinationVC, animated: true)

3.Using Delegation: You can define a protocol in the destination view controller and set the source view controller as its delegate. Then, you can call delegate methods in the destination view controller to pass data back to the source view controller.

protocol DataDelegate: AnyObject {
    func passData(data: YourDataType)
}

class DestinationViewController: UIViewController {
    weak var delegate: DataDelegate?

    // Call delegate method where you want to pass data
    delegate?.passData(data: // Your data to pass)
}

4.Using NotificationCenter: You can use NotificationCenter to broadcast a notification with the data, and the source view controller can observe this notification and retrieve the data.

In the source view controller:

NotificationCenter.default.post(name: Notification.Name("YourNotificationName"), object: nil, userInfo: ["data": // Your data])

In the destination view controller:

NotificationCenter.default.addObserver(self, selector: #selector(handleData(_:)), name: Notification.Name("YourNotificationName"), object: nil)

@objc func handleData(_ notification: Notification) {
    if let data = notification.userInfo?["data"] as? YourDataType {
        // Use the data
    }
}

5.Using Dependency Injection: Dependency injection involves passing dependencies, including data, from a higher-level component to its child components. You can inject the data into the destination view controller through its initializer or using a property setter.

class DestinationViewController: UIViewController {
    var data: YourDataType?

    // Initialize the view controller with data
    init(data: YourDataType) {
        self.data = data
        super.init(nibName: nil, bundle: nil)
    }

    // Alternatively, use a property setter
    func setData(_ data: YourDataType) {
        self.data = data
    }
}

In the source view controller:

let destinationVC = DestinationViewController(data: // Your data to pass)
// or
let destinationVC = DestinationViewController()
destinationVC.setData(// Your data to pass)

Choose the method that best fits your application’s architecture and requirements. Each method has its pros and cons, so consider factors such as code readability, maintainability, and performance when deciding which approach to use.

Consider these factors when selecting a method:

  • Data flow direction (one-way vs. two-way)
  • Complexity of data
  • Number of view controllers involved

For a deeper understanding, you can search for these terms online along with “iOS” to find tutorials and examples:

  • Segue with prepareForSegue
  • Delegation Pattern in iOS
  • Closures in Swift