与 if 语句相同的是,guard 也是基于一个表达式的 bool 值去判断一段代码是否该被执行。
与 if 语句不通的是,guard只有在条件不满足的时候才会执行这段代码。可以把 guard 近似看做是 Assert。
具体细节
简单的例子:
1 2 3 4 5 6 7 8 9 10
| func fooManualCheck(x: Int?) { if x == nil || x <= 0 { return } x!.description }
|
以上是最基本的 OC 方式来保证一个变量的值是否符合我们的要求。
有两个缺点:
- 你是在检查一个不符合你期望的条件,而并非你想要的值。
- 如果前面条件判断的结果不符合后,要想使用 x 你还得将变量强制拆包解绑。
使用 swift 可选绑定,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| func fooBinding(x: Int?) { if let x = x where x > 0 { x.description }
} ```
这样写代码会有一个缺陷,你可能目前并未察觉,但是如果真应用到项目中时,你会发现,你的代码被执行前,如果嵌套了很多需要被匹配的条件判断,会变得非常难以理解。
对此解决方法:对每个条件逐一检查,如果不符合条件判断就退出。会让人比较容易开出什么条件会让这个函数退出,这就是**保镖模式**。
于是就有了 guard 语句:
```swift func fooGuard(x: Int?) { guard let x = x where x > 0 else { return }
x.description }
|
这样写的好处:
- 相当于 if 的反向语句,{}内需要写的代码是条件不符合的代码。
- 如果通过了条件判断,可选类型的变量在 guard 语句被调用的范围内会被自动拆包 - 这个例子中,该范围是 fooGuard 函数内部。
- 对不希望的情况早做检查,让你写的函数更易读。
对非可选变量也是很好的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| func fooNonOptionalGood(x: Int) { guard x > 0 else { return }
}
func fooNonOptionalBad(x: Int) { if x <= 0 { return }
}
|