iosdevswift

Implement Delegate pattern in Swift

While teaching iOS development in Swift at iOS Akademija (here in Belgrade, Serbia), one of the most challenging topics for students to grasp is Delegate pattern.

I’m not sure why that is; most likely due to loose coupling and very asynchronous nature of the relationships between the relevant parties. Which are the very strengths of the pattern but those multiple moving parts are certainly adding to complexity. It takes some time and experience to recognize the need and the place for the pattern and internalize its implementation.

Teaching approach I like to use is to find a corresponding real-world problem and then map it into the pattern. So…

This is perfect fit for the Delegate pattern. So let’s implement it in Swift.

First, as in all good apps, we need to create proper data model for the Key == a description of work that needs to be done.

struct Key {
	var shape: String
}

Next, we need to model the Person, end user == the object that needs some work done.

final class Person {
	var name: String = "Me"

	var key: Key?
}

Lastly, let’s model the service which performs some function. Here Keymaker which makes the specific Key.

final class Keymaker {
	weak var customer: Keymaking?
}

Property customer models registration point for end users that need this specific work — key of type Key — done. In most iOS APIs, you will see the name delegate being used here; which is the common name used when implementing Delegate pattern. But that’s just developers using the same property name as the pattern itself. The actual name of the property is irrelevant and you can use whatever you want.

Notice two things here:

  1. customer is a singular item which implies the Keymaker can only work with one customer at the time. Thus it’s your job as developer to make sure that if one object assign itself as customer, no other object overrides or nullifies that assignment. Otherwise original Person will never receive its Key.
  2. Keymaker does not care what is the real, actual type of the entity/object that needs the Key made. It’s not Person, Company nor anything concrete. It’s actually a special abstract type, declared by the Keymaker which describes what any customer needs to implement in order to work with the Service.

In Swift, that’s done through protocols, which represent output interface declared by the Service to describe how it will deliver the result of its work.

protocol Keymaking: class {
	func keymaker(_ keymaker: Keymaker, didProduceKey key: Key)
}

Hence by saying that customer is of type Keymaking, Service actually says:

Person needs to indicate said agreement by adopting and implementing the given Keymaking protocol.

extension Person: Keymaking {
	func keymaker(_ keymaker: Keymaker, didProduceKey key: Key) {
		self.key = key
	}
}

Note that Keymaker does not care what its customer will do with the key. So it’s Person’s free will what will be inside this method above.

That’s why Swift protocols are perfect tool for the implementation of the Delegate pattern. They declare the intent and interface but don’t care about the actual implementation.

When Keymaker has produced the Key, it looks up customer’s contact info and makes the call / delivery using the method in its protocol:

fileprivate extension Keymaker {
	func didProduceKey(_ key: Key) {
		customer?.keymaker(self, didProduceKey: key)
	}
}

Note: this part is usually marked as (file)private for the Keymaker. No object outside the Keymaker should know nor care how the Key is produced.

Because you will usually have Key, Person and Keymaker all written in separate corresponding .swift files, then fileprivate helps Keymaker keep its trade secrets. Keymaker can change its internal process without fear that some nosy customer is trying to directly access parts of the Key making process. :)

I made example playground for all this code, which you can pickup from the repository at GitHub.com/radianttap.

I hope this was useful in understanding such crucial software design pattern. It’s very pervasive in iOS SDK thus any app developer needs to master it.

You will find it with UITextField which allows any other object conforming to UITextFieldDelegate protocol to control parts of its behavior and receive information when editing starts, stops etc.

UITableView uses it to offload input data to anyone implementing UITableViewDataSource. Through UITableViewDelegate it allows any other object to control parts of its look and behavior plus stay informed when something happens (i.e. row is selected).

Most importantly, Delegate pattern — along with Dependency Injection pattern — enables easy and straight-forward Composition of otherwise unrelated objects, views and controls. Mastering that technique places you well on the path to clean and easily maintainable code.