Delegate Pattern In Swift

A design pattern that enables a class or structure to hand off (or delegate) some of its responsibilities to an instance of another type

Arman
3 min readNov 14, 2021
The Delegate Pattern In Swift

Delegation is a design pattern that enables a class or structure to hand off (or delegate) some of its responsibilities to an instance of another type.

Swift Official Documentation

This pattern is implemented by defining a delegate protocol that encapsulates all the requests, a delegator who hands off the requests, and a delegate that implements the delegate protocol and provides requests that have been delegated. To better understand, imagine a new employee that came to the company; the boss (who knows everything) sends all the information and requests to the employee. Once the employee gets information, they will act and do what needs to be done.

Delegation can be used to respond to a particular action, or to retrieve data from an external source without needing to know the underlying type of that source.

Swift Official Documentation

To demonstrate how Delegation works in real projects, let's dive into an example:

User Interface:

I created a simple iOS project, in which we choose Lana Del Rey’s best album, and based on our selection, the main screen will be updated. Here is the interface of the project:

You can think of MainScreen as the employee and SelectionScreen as the boss.

Delegate Protocol:

First, create the delegate protocol which encapsulates all the functions or properties (things that need to be done) that the delegate object (the employee) must implement:

import UIKit// delegate protocol
// Things need to be done, commands
protocol AlbumSelectionDelegate {
func didTapChoice(image: UIImage, name: String)
}

Selection Screen:

Declare the delegate protocol and use the delegate in a class method to send data to a receiving class, which is any class that adopts the protocol:

import UIKit // delegator
// Boss; knows all information and things need to be done
class SelectionScreen: UIViewController {
var albumSelectionDelegate: AlbumSelectionDelegate! override func viewDidLoad() {
super.viewDidLoad()
}

@IBAction func blueBanistersTapped(_ sender: Any) {
albumSelectionDelegate.didTapChoice(image: UIImage(named: "ultraviolence")!, name: "Ultraviolence")
dismiss(animated: true, completion: nil)
}
@IBAction func bornToDieTapped(_ sender: Any) {
albumSelectionDelegate.didTapChoice(image: UIImage(named: "borntodie")!, name: "Born To Die")
dismiss(animated: true, completion: nil)
}
}

Main Screen:

Adopt the delegate protocol in MainScreen class and assign self to the delegate property of SelectionScreen, which means the current instance of MainScreen is the delegate of the SelectionScreen. Then implement the method provided by the delegate protocol to respond to events happening in the SelectionScreen:

import UIKit // delegate Object
// Employee; waiting for commands
class MainScreen: UIViewController, AlbumSelectionDelegate {
@IBOutlet weak var nameLabel: UILabel!
@IBOutlet weak var mainImageView: UIImageView!
@IBOutlet weak var chooseButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func chooseButtonTapped(_ sender: UIButton) {
let selectionVC = storyboard?.instantiateViewController(withIdentifier: "SelectionScreen") as! SelectionScreen
selectionVC.albumSelectionDelegate = self
present(selectionVC, animated: true, completion: nil)
}
func didTapChoice(image: UIImage, name: String) {
mainImageView.image = image
nameLabel.text = name
}
}

And finally when we run the project on the simulator:

Delegate pattern is also used by Apple in classes such as UITableViewDelegate, UITableViewDataSource, UICollectionViewDelegate, etc. Here is a typical example of implementing one of the most famous Apple delegate protocols:

import UIKitclass ViewController: UIViewController, UITableViewDelegate,UITableViewDataSource {    @IBOutlet weak var tableView: UITableView!

override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// ...
}


func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// ...
}


func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// ...
}
}

You can download the source code from here.

--

--

Arman

Code, conquer, and share. I write about software development and coding challenges. Let's learn and grow together! armanabkar@gmail.com