What is a Delegate in Swift?


In this article, you will learn about what Delegate is and how it works.

What is Delegation?

As the name implies, delegation gives control to other objects. To make it happen, the delegate object has to be assigned to control other objects.

In iOS apps, the UIApplicaitonDelegate is an example. UIApplicationDelegate allows you to modify iOS behavior, such as receiving push notifications, opening URLs, and launching apps.

A delegation pattern ensures the functionality that needs to be delegated is provided.

Delegate patterns enable objects to communicate back to their owners decoupled from their code. It is much easier to reuse and maintain code if an object does not have to know the concrete type of its owner.

What is The Protocol in Swift?

A protocol acts as a tool to combine properties and methods into a single entity so that other objects can conform to this protocol to delegate tasks.

We can implement the properties and functions of protocols that can be provided by a class, structure, or enumeration in Swift. It is said to conform to a protocol if any of these types meet its requirements.

The Syntax For Creating a Protocol

Syntax

protocol <protocol_name> {
   // define the required methods here
}

As shown above, we gave a protocol name to our protocol which is specified using the protocol keyword in Swift. By defining your methods based on the protocol's requirements, you can define the protocol's purpose.

Creating a Delegate Object

Let’s try to understand how to use delegate in ImageDownloader class. I keep an optional reference to the delegate object (of type ImageDownloader) to allow an ImageDownloader class instance to operate without a delegate. If the delegate member variable is nil, ImageDownloader still downloads a file and still calls its own didDownloadImage() method.

import UIKit class ImageDownloader { var urlString: String var downloadedImage: UIImage? var delegate: ImageDownloaderDelegate? init(_ urlString: String) { self.urlString = urlString } func downloadImage() // downloading image DispatchQueue.global(qos: DispatchQoS.QoSClass.default).async { let imageURL = URL(string: self.urlString) let imageData = NSData(contentsOf: imageURL!) self.downloadedImage = UIImage(data: imageData! as Data) // update UI action on main thread DispatchQueue.main.async { self.didDownloadImage() } } } func didDownloadImage() { delegate?.didFinishDownloading(self) } }

Creating a Protocol

Using the ImageDownloader class, we will define a protocol to notify conformed objects when a task is completed or failed. This protocol will have a set of rules (or functions).

A class, struct, or enum can conform to the protocol and complete the implementation of these functions.

In this example, we will conform to the ImageDownloaderDelegate protocol in the ProfileController class. Now, we need to set the delegate object to ProfileController’s object.

Make sure that the required functions are implemented in the ProfileController class. Otherwise, the compiler will report an error.

import UIKit // Protocol Creation protocol ImageDownloaderDelegate { // notify when downloading will be finished func didFinishDownloading(_ sender: ImageDownloader) // notify when downloading will be failed func didFailedDownloading(_ sender: ImageDownloader) }

Conforming to This Delegate

Now, the ProfileController class conforms to the ImageDownloaderDelegate protocol.

class ProfileController: UIViewController, ImageDownloaderDelegate { private var imageDownloader: ImageDownloader? private let profileImageView = UIImageView() override func viewDidLoad() { super.viewDidLoad() view.addSubview(profileImageView) // set profileImageView frame here as per requirement downloadImage() } private func downloadImage() { let imageURL: String = "<https://image_url_here>.com" imageDownloader = ImageDownloader(imageURL) imageDownloader?.delegate = self imageDownloader?.downloadImage() } func didFinishDownloading(_ sender: ImageDownloader) { profileImageView.image = sender.downloadedImage let urlString = sender.urlString print(urlString) } func didFailedDownloading(_ sender: ImageDownloader) { profileImageView.image = nil } }

How to Make The Optional Protocol Method?

You can include optional methods in your protocol. You have to create an extension for your optional protocol methods.

// protocol creation protocol ImageDownloaderDelegate { // notify when downloading will be finish func didFinishDownloading(_ sender: ImageDownloader) // notify when downloading will be failed func didFailedDownloading(_ sender: ImageDownloader) } extension ImageDownloaderDelegate { func didFailedDownloading(_ sender: ImageDownloader) { } }

Conclusion

You delegate work to someone/something else who can do it. Delegation helps you separate concerns, decouple classes, and make your code more reusable. The best place to start with delegation is between your view and your view controller

Updated on: 21-Dec-2022

3K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements