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

inside the ViewModel class called Declare a typealias of type Result -> () called Closure

called Remove the delegate variable, the init and the extension at the bottom

Modify the function declaration to have a Closure argument

argument Inside the get function, we need to switch on the response to get either the result or the error from the call.

function, we need to on the to get either the or the 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