Swift Alley: Defer Statements

Every so often I come across an amazing feature in Swift that leaves me astonished. I wonder how I had not come across it sooner. Discovering Swift’s defer statement was one of those times.

The idea behind defer is simple: anytime you want to ensure a block of code is called before exiting your current scope, simply place the block of code inside a defer statement.

Example Without Defer

Let us use a simple example. We have a function that takes a completion handler:

Swift

1

2

3

4

5

6

7

8

funcmyFunc(completionHandler:()-&gt;Void){

guard letsomeData=json["data"]as?Stringelse{

completionHandler()

return

}

// Do stuff with data

completionHandler()

}

We have two points in which we exit the scope of this function:

Our guard statement’s else clause requires we exit the scope.

When our function naturally runs its course end.

It is redundant to have to call completionHandler() at both of these points. Let’s be faithful to the DRY principle (Don’t Repeat Yourself) and give this another go. How do we ensure completionHandler() gets called regardless of how we end up exiting this function?

Defer Saves the Day

Enter the defer statement. See the same example, now with the defer statement in use:

Swift

1

2

3

4

5

6

7

8

9

10

11

funcmyFunc(completionHandler:()-&gt;Void){

// Call completionHandler just once

defer{

completionHandler()

}

guard letsomeData=json["data"]as?Stringelse{

return

}

// Do stuff with data without worrying about calling completionHandler()

}

No matter how this function returns, I am guaranteed completionHandler() will get called. I find this to be more elegant than plastering calls at every possible exit.

I should mention that you can have multiple defer statements in a given scope. They will get called from the latest to the earliest (Last In, First Out).

Swift

1

2

3

4

5

6

7

8

9

10

11

12

13

funcmultipleDefers(){

defer{

print("first defer statement")

}

defer{

print("second defer statement")

}

}

multipleDefers()

// second defer statement

// first defer statement

Why would you want to use multiple defer statements, you ask? Well, as your function is executed, there may be new data that was not available early on, and you need to perform an action with it before exiting the function. Whatever the case may be, use defer wisely! 🙂

A Word of Caution

There are a few quirks with defer statements that I should mention. First, never ever use a return statement inside a defer block. Second, avoid calls to functions that could throw an error. Doing either of these may cause your application to crash. Apart from that, knock yourself out!

Conclusion

You are bound to come across scenarios where defer will come in handy. Keep an eye out for opportunities to use it like with clean-up code, do-blocks, and loops. It not only eliminates repetition (DRY!), but also improves clarity and guarantees execution. I will take clean, succinct, and robust code any day!

The “Swift Alley” series covers powerful language features that are often overlooked due to it being tucked away in the darkest corners of Swift.