3️⃣Delegation
Fall 2023 | Vin Bui
This is one of the most important concepts to understand regarding iOS development using UIKit, and is one of concepts that students in the past have struggled with the most. Please read this section over and over again until you understand this concept. Feel free to ask the course staff if you are still confused.
The main purpose of the delegate pattern is to allow a child to communicate back with its parent without the child knowing its parent’s type. This makes it much easier to maintain and write reusable code. Delegation is a 1:1 relationship with a child and its parent.
Protocols
To implement delegation in Swift, we use protocols. According to Swift’s official documentation,
A protocol defines a blueprint of methods, properties, and other requirements that suit a particular task or piece of functionality. The protocol can then be adopted by a class, structure, or enumeration to provide an actual implementation of those requirements. Any type that satisfies the requirements of a protocol is said to conform to that protocol.
In other words, protocols are a set of properties and methods that classes must implement when conforming to it (similar to interfaces in Java).
You can learn more about protocols here, but for our purpose, we will only need to define functions inside of the protocol. For example, If we wanted to create a protocol so that a child can tell its parent to update some text, we could do the following:
Make sure to conform the protocol to AnyObject
!
It’s convention to name our protocol with its purpose followed by the word Delegate
at the end. We also created a function called updateText
that takes in a string called newText
. Now, if we had a class called ParentViewController
and we wanted to conform to this protocol, we could do the following:
Now, it’s common to use an extension to implement these functions to keep our code a lot more neat:
The only changes that we made was removing UpdateTextDelegate
from the original class header and moved it to the extension header, followed by the function implementation required by the protocol.
Delegate vs Delegator
In the code above, we conformed ParentViewController
to the UpdateTextDelegate
protocol. The class ParentViewController
is known as the delegate. The delegate is the class that conforms to that protocol.
Now, if we had a view controller called ChildViewController
that wants to communicate back with the parent, then this view controller is known as the delegator. The delegator is the class that wants the delegate to do something by calling the delegate.
We’ve looked at the code required by the delegate, but what about the delegator? Inside of ChildViewController
, we would create a property whose type will be UpdateTextDelegate
:
How does this child class know who the delegate is? The parent class would need to specify that it itself is the delegate:
Now, once the child has a reference to its parent (specifically, a weak reference, will explain this in another chapter), we can now call that function:
Note: In the example code above, we created the functions pushChildVC
and communicateBack
. These functions could be anything. What’s important is the code inside of the function.
Putting everything together
There was a lot of code and it could be quite difficult to wrap our head around, so let's put everything together.
There are two classes: ParentViewController
(delegate) and ChildViewController
(delegator). ParentViewController
is the delegate so it conforms to the protocol, meaning that it is required to implement the functions and properties defined by that protocol. When ParentViewController
creates the ChildViewController
, it will need to tell it that it itself is the delegate. We do this by creating a property in ChildViewController
containing the reference of the delegate (which is ParentViewController
). To communicate from the child to the parent, the child calls the function defined in the protocol using the delegate property that was created earlier. This child could then pass in whatever it wants to the function (since it’s the delegator) and the parent (the delegate) will use whatever the child passed in and do whatever it needs to do.
Let’s take a real life example to understand this better. Say we went to a bar to have a couple of drinks. The bar contains a menu, a bartender, and a customer. The menu is the protocol, the bartender is the delegate, and the customer is the delegator. The bartender must conform to the menu. In other words, the bartender can only make drinks that are on the menu. But how does the bartender know what drinks to make? Well, the customer (delegator), tells the bartender (delegate) what drinks to make. In other words, the customer cannot make the drinks themself but requires the bartender to do it for them.
Last updated