Using Enums and Closures to Substitute Delegates

David Martínez-Lebron
ITNEXT
Published in
3 min readJul 3, 2018

--

Photo by Hello I’m Nik on Unsplash

As iOS developers, we are used to using delegates to move data asynchronously, and Apple sure loves to use them as well.
However, if you are like me (and many other iOS developers), avoiding using them is a significant part of our development steps, especially when using MVVM without RxSwift (or any other functional reactive programming library).

We are going to use closures in combination with enums to avoid using delegates between the ViewModel and the ViewController.
The project that we’ll work on uses delegates, and we will refactor it to use enums and closures instead.

If you are not familiar enough with closures, I recommend you take a look at this one first: Don’t abuse Delegates, Use Swift Closures Instead

First, visit here to get the initial project.

Let’s run the app to get an idea of how it works:

Is a straightforward app, it has an Api Client, a View Model, and one View Controller.
The Api Client makes the network call to get all the jobs, then sends the objects to the View Model and the View Model notify the View Controller about the loading state and passes the objects to be shown.
All these calls are asynchronous. Therefore we are using delegates to pass the data from the Api Client all the way to the View Controller.

Refactoring:

Api Client
Here we have two delegates:

Let’s begin creating an enum inside the ApiClient class called Response.

Now let’s create a typealias for our closure statement.

We are almost done, now let’s modify the function signature to have our just declared Closure typealias.

Great, now lets put all the pieces together.
After replacing the delegate methods calls with the new closure argument, and deleting every related to ApiClientDelegate inside the class, it should look like this.

Awesome!
By now you should be getting a bunch of errors on the View Model, but don’t worry, we’ll take care of that right away.

View Model
Following the same pattern that we just did in the ApiClient, we need to:

  • Add an enum inside the ViewModel class called Result
  • Declare a typealias of type Result -> () called Closure
  • Remove the delegate variable, the init and the extension at the bottom
  • Modify the function declaration to have a Closure argument
  • Inside the get function, we need to switch on the response to get either the result or the error from the call.
  • After all of these steps are done, the class should look like this:

And now… Dejavu
The View Controller is now screaming for help, let’s jump right in.

View Controller
The first thing we could do is to modify the View Model init method because it doesn’t expect a delegate anymore, modify the getJobs() function signature and remove the extension that conforms to ViewModelDelegate.

As you can see, we can change the viewModel variable to be a let instead of a lazy var and now, let’s switch over the result just like we did on the View Model.

And that’s that… wait…
We are creating a reference cycle by calling self inside the closure. To fix it let’s use the following capture list [unowned self] before the (result) in the closure. There’s a lot of controversy whether you should use [weak self] or [unowned self] but for this example, using unowned is the right call.

Run the app, and everything should be working as expected.

Scalable:

In case you have more than two delegates (like in this example) you can quickly scale your enum to have more cases. This is what makes this approach attractive, is clean, easy to follow and easy to scale.

To download the final project, visit here.

Follow me

Twitter: dmlebron

--

--