Stop Abusing Delegates. Use Swift Closures Instead
Tags: swift, ios, closures
Published: 2021-01-25 01:42:34

# Don’t abuse Delegates. Use Swift Closures Instead

As iOS developers, we tend to use many delegates, sometimes even abusing these poor little fellas. But, what else can we use? Right?

We know a few other options, but they might feel awkward or a bit of an overkill, depending on what we want to accomplish.

## Real-World Example

If you've been programming in iOS before introducing the `UIAlertController` (iOS 8), you probably used its predecessor alert, UIAlertView. One of the most noticeable changes between these two alerts is the way they interact with their caller. TheUIAlertView notified the view controller about the button events using delegates, while the UIAlertController uses a closure of type `((UIAlertAction) -> Void)?`. In my opinion, this change was a significant improvement, which provides developers a cleaner way to implement the alert.

In this tutorial, we will create a simple "note-taking" (almost useless) app. We will be using the closure pattern as an alternative to the frequently used, practically abused delegate pattern.

## What you'll need for this tutorial

- Xcode 12
- Swift 5
- Some experience working iOS
- High-level understanding of swift optionals

Download the starter project [here](https://github.com/dmlebron/tutorial_closures/tree/starter).

Open the project and navigate (`shift + command + o`) to `SecondViewController` . Here, notice I added two methods, `cancel()` and `update()`. The `cancel()` will `dismissSecondViewController` and `update()` will notify the caller about the action. It’s important to notice that all `update()` method logic will be handled by the caller (in this scenario, the `ViewController`).

## But, what the heck is the `buttonAction` variable type?

The `buttonAction` variable is of type `((String?) -> ())` meaning the variable is a function (just like blocks in Objective-C). This approach is possible in swift because functions are first-class citizens (often call first-class objects).

Let's discuss each part of our `buttonAction` type: `((String?) -> ())?`. To make it very clear, let's identify each part of it.

- `String?`: this means that `buttonAction` can pass on an optional `String` (can have a string or be nil).
- `->`: identifies the "arguments" and what is the "returned" (just like functions). We'll only work with the first part (the arguments).
- `()`: this is equivalent to `Void`. It says that nothing is expected.

It’s important to notice that `((String?) -> ())?` is of type optional. therefore ViewController not necessarily needs to implement the `buttonAction` variable. In case the variable is not implemented (`buttonAction == nil`), the SecondViewController will only be dismissed.

Great! Now, let's use this pattern to pass information from SecondViewController to ViewController.

## Implementing Swift Closures to Pass Data Between UIViewControllers

Let's implement the `buttonAction` variable on the ViewController. Add the following code on the ShowViewController(sender: UIButton) method just on top of the present(...) line.

```swift
secondViewController.buttonAction = { text in
  textLabel.text = text

  return secondViewController.dismiss(animated: true, completion: nil)
}
```

If you try to run your code now, you should get an error like this one:

![error](https://dev-to-uploads.s3.amazonaws.com/i/1h6i5uhyg3ptt2hmmmf3.png) 

This means that we need to add the Objective-C extremely used self on our `textLabel` variable. To avoid a reference cycle, instead of referencing self directly, we will use capture list and reference `weak self` instead.

```swift
secondViewController.buttonAction = { [weak self] text in
  textLabel.text = text

  return secondViewController.dismiss(animated: true, completion: nil)
}
```

Right, it's not required anywhere else on the ViewController, but we are now inside our closure declaration, and inside closures, you need to reference `self`. It's a good practice to use [weak self], [unowned self], or the property that you will reference inside the closure ([textLabel] in this specific case) to avoid reference cycles. If you use the property instead of weak or unowned, you don't need to use `self`.

The error must have disappeared by now, and you should be able to run the project and test everything you just did.

Coming back to our `buttonAction`, as we mentioned before, it is a closure, and closures are like functions.

So, we declare the variable to a function with a variable text and a return value of type `()`, which is the same as `Void`.

## Conclusion

Most of the time, iOS programmers overuse delegates since they don't like the Objective-C block syntax (not my case, I used to love that weird syntax). This article demonstrated that it is possible to use a closure to pass information from one view controller to another.

---

We just used closure to pass information from one view controller to another. As iOS developers (and if you are coming from Objective-C), we sometimes used the Delegate pattern a lot.

Some people didn't like Objective-C block syntax (I used to love that weird syntax, though).

Now, with Swift closures, we can set aside those good ol' Delegates.

[Download final project](https://github.com/dmlebron/tutorial_closures/tree/final)

## Follow me

Twitter: [dmlebron](https://twitter.com/dmlebron)