全局和嵌套函数实际上也是特殊的闭包。闭包采取如下三种形式之一:
| 类型 | 说明 |
|---|---|
| 全局函数 | 名字但不会捕获任何值的闭包 |
| 嵌套函数 | 有名字并且可以捕获其封闭函数域内值的闭包 |
| 闭包表达式 | 用轻量语法所写的可以捕获其上下文中变量或常量值的匿名闭包 |
闭包表达式语法
Swift 中的闭包表达式很灵活,其标准语法格式如下:
{
(参数列表) -> 返回值类型 in
函数体代码
}
其中,参数列表与函数中的参数列表形式一样,返回值类型类似于函数中的返回值类型,但不同的是后面有in关键字(分割返回值类型和函数体代码)。
-
尾随闭包
将闭包表达式作为最后一个参数传递给函数,将这个闭包替换成为尾随闭包的形式很有用。
尾随闭包是一个书写在函数圆括号之后的闭包表达式,函数支持将其作为最后一个参数调用
func someFunctionThatTakesAClosure(closure: () -> Void) {
// 函数体部分
}
// 以下是不使用尾随闭包进行函数调用
someFunctionThatTakesAClosure(closure: {
// 闭包主体部分
})
// 以下是使用尾随闭包进行函数调用
someFunctionThatTakesAClosure() {
// 闭包主体部分
}
如果闭包表达式是函数或方法的唯一参数,则当你使用尾随闭包时,你甚至可以把 () 省略掉:
func addFunc(add: (Int, Int) -> Int) {
print(add(1, 2))
}
addFunc {
$0 + $1
}
-
类型推断简化
由于在调用函数传入闭包表达式参数时,形参的sum参数可以推断入参和返回值是 Int,则可以简化
sumFunc(v1: 1, v2: 2, sum: {
number1, number2 in
return number1 + number2
})
-
隐藏return关键字
如果在闭包内部语句组只有一条语句,如return a + b等,那么这种语句都是返回语句。前面的关键字return可以省略,省略形式如下: {number1, number1 in number1 + number1 } 所以:
sumFunc(v1: 1, v2: 2, sum: {
number1, number2 in
number1 + number2
})
-
缩写参数名称
Swift自动为内联闭包提供了简写参数名称,可以使用这些名称1、$2等来引用闭包参数的值。
如果在闭包表达式中使用这些简写参数名称,则可以从其定义中省略闭包的参数列表,简写参数名称的数量和类型将从预期的函数类型中推断出来。in关键字也可以省略,因为闭包表达式完全由其主体组成:
sumFunc(v1: 1, v2: 2, sum: { $0 + $1 })
-
运算符方法
还有一种更短的方法来编写上面的闭包表达式。Swift的String类型将大于运算符(>)特定于字符串的实现定义为一个方法,该方法有两个String类型的参数,并返回Bool类型的值。这与sorted(by:)方法所需的方法类型完全匹配。因此,我们只需传入大于运算符,Swift将推断我们希望使用大于运算符特定于字符串的实现:
reversedNames = names.sorted(by: >)