Swift 101. Delegates between UIViewControllers

Swift 101: Mastering Delegates in UIViewControllers - Dive into the fundamentals of using delegates to manage communication between UIViewControllers in Swift. This beginner-friendly guide provides clear examples and best practices to enhance your iOS app development skills. Essential reading for new Swift developers looking to understand delegation patterns.

Swift 101. Delegates between UIViewControllers
Do not index
Do not index
notion image
From left to right: NavigationController, OriginController, TopBottomController, LeftRightController
Today I would like to answer a question I got quiet often lately. How do you transfer information between UIViewControllers that are connected with a UINavigationController.
This scenario is very common. A typical scenario is the Settings App of the iPhone’s iOS. We navigate from controller A to controller B using a navigation controller, we send information from A to B and from B back to A.
notion image
Example: iOS Accessibility Settings
In this article I will talk about the 2 most common approaches. A segue using the storyboard and the init with dependency.

The Keyword: Delegate

The idea with our small test project is that we have an origin controller with two buttons and a label. If we press the “Pick Navigation” button, we will present the TopBottomController using a segue. And on “Pick Presentation” we will present the LeftRightController.
If we press one of the buttons in TopBottomController or LeftRightController, we will dismiss/pop the controllers and send the selection back to the origin controller and present the selection in the label.
TopBottomController will have the TopBottomControllerDelegate and LeftRightController the LeftRightControllerDelegate.

TopBottomControllerDelegate

protocol TopBottomControllerDelegate {
   func topBottomController(topButtonPressed: Bool)
}

LeftRightControllerDelegate

protocol LeftRightControllerDelegate {
   func leftRightController(leftButtonPressed: Bool)
}

Connecting the delegates

When presenting our TopBottomController we’re using a storyboard segue by calling:
@IBAction func navigationButtonPressed(_ sender: Any) {
   performSegue(withIdentifier: "navigationSegue", sender: self)
}
To connect the segue, we need to prepare the destination controller in the method: prepareForSegue:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
   if segue.identifier == "navigationSegue" {
      let controller = segue.destination as! TopBottomController
      controller.delegate = self
   }
}
Next we need to implement the TopBottomControllerDelegate into our OriginController. And handle the action (in our case update the label).
// MARK: - TopBottomControllerDelegate
extension OriginController: TopBottomControllerDelegate {
   func topBottomController(topButtonPressed: Bool) {
     self.selectionLabel.text = topButtonPressed ? "Top" : "Bottom"
   }
}
Same for our LeftRightControllerDelegate.
// MARK: - LeftRightControllerDelegate
extension OriginController: LeftRightControllerDelegate {
   func leftRightController(leftButtonPressed: Bool)
     self.selectionLabel.text = leftButtonPressed ? "Left" : "Right"
   }
}
And now to be able to send the selected button back from our TopBottomController to our OriginController, all we need to implement is the following into our TopBottomController:
class TopBottomController: UIViewController {   public var delegate: TopBottomControllerDelegate!   @IBAction func topButtonPressed(_ sender: Any) {
      self.navigationController?.popViewController(animated: true)
      self.delegate.topBottomController(topButtonPressed: true)
   }   @IBAction func bottomButtonPressed(_ sender: Any) {
      self.navigationController?.popViewController(animated: true)
      self.delegate.topBottomController(topButtonPressed: false)
   }
}
As you can see, we pop the controller using our navigationController and then call the delegate with our selection. The result will be the selected button presented in our origin controller’s label.
notion image
The same logic applies to our dependency injected LeftRightController. When we press the “Pick Presentation” button, we’re presenting the controller that we’re initiating as following:
private var leftRightController: LeftRightController {
   let storyboard = UIStoryboard.init(name: "Main", bundle: nil)
   let controller = storyboard.instantiateViewController(withIdentifier: "LeftRightController") as! LeftRightController
   controller.delegate = self
   return controller
}
As you can see, we are here as well defining the delegate to self. Lastly we just need to call our controller:
@IBAction func presentationButtonPressed(_ sender: Any) {
   self.present(leftRightController, animated: true)
}
And dismiss and call our delegate when the user clicks on of the buttons.
class LeftRightController: UIViewController {   public var delegate: LeftRightControllerDelegate!   @IBAction func leftButtonPressed(_ sender: Any) {
      self.dismiss(animated: true)
      self.delegate.leftRightController(leftButtonPressed: true)
   }   @IBAction func rightButtonPressed(_ sender: Any) {
      self.dismiss(animated: true)
      self.delegate.leftRightController(leftButtonPressed: false)
   }
}
And as a result our label will now present the left/right selection as expected.
notion image
I hope this story explained to you the basics and power of the delegates. Of course we could have cleaned the code, refactored and made it very fancy, but I wanted to keep it simple so everyone can understand it. Leave some love 🙂

Ready to take the next big step for your business?

Join other 3200+ marketers now!

Subscribe