DePhoto by Jason Rosewell on Unsplash

Delegation pattern in Swift

Moritz Lang
Slashkeys Engineering
3 min readFeb 15, 2018

--

How children should talk to their parents 👨‍👩‍👧‍👦

Let’s imagine we have two objects, FeedViewModel & TwitterAPI. An instance of TwitterAPI is stored as a property called twitterAPI inside the FeedViewModel:

class TwitterAPI {}class FeedViewModel {
private let twitterAPI = TwitterAPI()
}

Sending a message from FeedViewModel to TwitterAPI is fairly easy as we can call a method or set a property on twitterAPI, but communicating back from TwitterAPI to FeedViewModel is a bit more complex, because it doesn’t have a direct connection to FeedViewModel.
Of course we could add this connection by adding a property feedViewModel: FeedViewModel to TwitterAPI, but this isn’t really flexible as we might want to use the TwitterAPI in other scenarios where the parent object is no FeedViewModel. In that case we would have to add a property for each use-case of TwitterAPI.

Currently no connection from TwitterAPI to FeedViewModel exists. 💔

One possible solution is to use the Delegation pattern.

It all starts with a protocol

protocol TwitterAPIDelegate: class {
func didRetrieveTweets(_ tweets: [Tweet])
}

Now we can add a property (usually called delegate) to TwitterAPI:

class TwitterAPI {
weak var delegate: TwitterAPIDelegate?
}

By setting the type of delegate to TwitterAPIDelegate we can ensure that the value it stores implements all methods required by the protocol. By extending FeedViewModel to conform to TwitterAPIDelegate it becomes one possible candidate for this value.

You may have noticed that delegate is a weak property. This is used to avoid a retain cycle between FeedViewModel and TwitterAPI. You can read more about retain cycles and Swift’s memory management in an upcoming post. For now just keep in mind that we need to add the : class requirement to the delegate so that we can make the property weak.

Via an extension on FeedViewModel we can add the implementation for didRetrieveTweets.

extension FeedViewModel: TwitterAPIDelegate {
func didRetrieveTweets(_ tweets: [Tweet]) {
// display the tweets
}
}

Inside FeedViewModel's initializer we can set itself as the value of twitterAPI's delegate property:

class FeedViewModel {
private let twitterAPI = TwitterAPI()
init() {
twitterAPI.delegate = self
}
}
The delegate property now connects TwitterAPI to FeedViewModel ❤️

Using our newly created connection

Now that we established the missing connection we can notify FeedViewModel about events from TwitterAPI by simply calling the methods on delegate.

class TwitterAPI {
weak var delegate: TwitterAPIDelegate?
func connect() {
// do some network calls ⏱
delegate?.didRetrieveTweets(tweets)
}
}

Because the value of delegate is set to FeedViewModel's self the view model’s implementation of didRetrieveTweets will be called. 🧙‍♀️

Conclusion

As you can see the Delegation pattern is a simple, yet elegant, solution for communication between child-objects and their parents / owners.

What do you think about this approach? Do you still have some questions left or do you prefer other solutions over this?

Thanks for reading ✌️

--

--

Moritz Lang
Slashkeys Engineering

Swift Developer / Software Engineering student @codeuniversity