The keyword guard has been introduced in Swift 2. It was a little bit inconspicuous at the first sight, but it has a lot of power. In this article we will take a look at three uses cases for guard.
Hint: This post has been updated to Swift 3 and Xcode 8
Avoiding The Pyramid Of Doom
Using
guard is very good way to avoid the pyramid of doom . Let’s take a look at an example from a previous post. We are creating a function that calculates the area of a circle:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import Foundation
enum CircleAreaCalculationError : Error {
case RadiusNotSpecified
case RadiusUnvalid
}
func calculateCirlceArea ( radius : Double ? ) throws -> Double {
if let radius = radius {
if radius > 0 {
return radius * radius * M _PI
} else {
throw CircleAreaCalculationError . RadiusUnvalid
}
} else {
throw CircleAreaCalculationError . RadiusNotSpecified
}
}
It works, but you can see that there are a lot of
if and
else keywords. And that’s not very good to read. If you have a lot of nested indentations, you are speaking of “the pyramid of doom”. Our example is not very extreme, but there are a lot of real world examples where you have a lot of nested indentations.
By using
guard you can make the code much more readable:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import Foundation
enum CircleAreaCalculationError : Error {
case RadiusNotSpecified
case RadiusUnvalid
}
func calculateCirleArea ( radius : Double ? ) throws -> Double {
guard let radius = radius else {
throw CircleAreaCalculationError . RadiusNotSpecified
}
guard radius > 0 else {
throw CircleAreaCalculationError . RadiusUnvalid
}
return radius * radius * M _PI
}
There’s also see another great benefit in this example: If you are using
guard for unwrapping an optional, the variable becomes available as a non-optional after the
guard block. By using optional chaining you can only use it within the
if block.
Throwing Errors
Since Swift 2 there’s been a complete new error handling model . It uses a do-try-catch syntax. As you can see in the previous example,
guard is a very good place to throws errors:
guard radius > 0 else {
throw CircleAreaCalculationError . RadiusUnvalid
}
In my opinion that is an excellent use case for
guard .
API Availability Checking
Every year Apple releases a new major iOS update, and with each update there are new features and APIs. But since it is not unusual for an App to support at least the previous iOS version, you have to be careful in using these new APIs. The API availability checking feature is very handy in these situations.
Without using
guard , you can do this for example like this:
func configureForceTouch ( ) {
if # available ( iOS 9.0 , * ) {
if ( traitCollection . forceTouchCapability == UIForceTouchCapability . available ) {
//configure force touch
}
}
}
By using
guard , your code becomes much more readable:
func configureForceTouch ( ) {
guard # available ( iOS 9.0 , * ) else {
return
}
if ( traitCollection . forceTouchCapability == UIForceTouchCapability . available ) {
//configure force touch
}
}
This is also a special case of avoiding the pyramid of doom.
Video
VIDEO
References
Optionals In Swift
Swift 2: guard
Swift 2.0: API Availability Checking
Image: @ David Pereiras / shutterstock.com