DEV Community

Luka Bubalo for Bornfight

Posted on

The basics of using the delegation pattern

Why?

Recently I’ve started with the development of iOS applications and stumbled upon an interesting design pattern called delegation pattern. Abstractly talking, the main idea behind this pattern is to receive and process information in class A when something happens in class B.
In this case, class A is the delegatee/worker, and class B is delegator/master. Specifically, when something happens on screen B, we want screen A to act accordingly. Also, the really good thing about this pattern is that you can have as many workers/delegatees as you want, they just need to implement the protocol.

I will give you an example written in Swift, but this can, of course, be applied in any other programming language which supports the object-oriented paradigm.

How?

Let’s say we have two screens, the first one is a profile screen where all information about the profile is shown like nickname, country, you name it.
The second one is the settings screen where we can change those profile information. What we want to achieve is that when we adjust that information on the settings screen and click the save button, we want that data to be propagated back to our profile screen. So basically, the settings screen is a delegator and the profile screen is a delegatee who will receive the data from its delegator and display it.

Before we start with the code example, let’s see what the flow for implementing delegate pattern looks like:

  1. Define the delegate protocol
  2. Add delegate property in the delegator
  3. Extend the delegatee class so it implements the delegate protocol
  4. Assign the delegatee object as delegate property in the delegator
  5. Call the delegatee from the delegator

Here is the code example:

Note: if you are not familiar with Swift, the protocol is the same as the interface in languages like Java, C#, PHP, etc.

protocol MyProfileSettingsViewControllerDelegate: AnyObject {
    func didChange(profile: Profile)
}

class MyProfileSettingsViewController: UIViewController {

    // ...

    weak var delegate: MyProfileSettingsViewControllerDelegate?

    let saveButton = UIBarButtonItem(title: "Save", style: .plain, target: self, action: #selector(saveButtonTapped))

    func saveButtonTapped() {
        let profile = Profile(...) // populate Profile model with new data
        delegate?.didChange(profile: profile) // pass updated Profile model to delegatee

        // navigate to the profile screen
    }

    // ...
}
Enter fullscreen mode Exit fullscreen mode
class MyProfileViewController: UIViewController {

    // ...

    let settingsButton = UIBarButtonItem(title: "Settings", style: .plain, target: self, action: #selector(settingsButtonTapped))

    func settingsButtonTapped() {
        let controller =  MyProfileSettingsViewController()
        controller.delegate = self // assign this object as delegatee

        // navigate to the profile screen
    }

    func updateInfo(profile: Profile) {
        nicknameLabel.text = profile.nickname
        countryLabel.text = profile.country
        //...
    }

    // ...

}

extension MyProfileViewController: MyProfileSettingsViewControllerDelegate {
    func didChange(profile: Profile) {
        updateInfo(profile: profile) // update your view with new profile data adjusted on the settings screen
    }
}
Enter fullscreen mode Exit fullscreen mode

I hope this was helpful to you. If you have any questions, feel free to leave them in the comments below. :)

Thank you for reading!

Top comments (0)