Trailing Closures(尾闭包)
如果你需要将一个闭包表达式作为参数传递给一个函数,而且参数的位置刚刚好是函数的最后一个,你这个闭包表达式又很长,那么使用尾闭包就显得非常有效(有用).
尾闭包是一个写在跟随函数()外面(或后面)的闭包表达式:
func someFunctionThatTakesAClosure(closure: () -> ()) {
// function body goes here
}
// here's how you call this function without using a trailing closure:
someFunctionThatTakesAClosure({
// closure's body goes here
})
// here's how you call this function with a trailing closure instead:
someFunctionThatTakesAClosure() {
// trailing closure's body goes here
}
注意点:
如果一个闭包表达式是函数的唯一参数,而且你又使用了尾闭包的方式,那么你在调用函数的时候,可以只使用函数名,而不用写上一对小括号()
前面提过的字符串排序闭包,就可以使用尾闭包的方式:
reversed = sort(names) { $0 > $1 }
当闭包表达式非常长,以至于一行无法写完的情况下,尾闭包就会显得非常有用.举个例子,Swift中的Array类型有一个map方法,它接收一个闭包表达式作为一个参数, 在数组内每个元素都调用一次这个闭包,返回一个针对这个元素修改过的map值(可能是其他类型),这些都根据闭包来指定.
在对数组中每个元素应用了闭包之后,map方法返回一个新数组,它包含新的映射值与原数组序列相同.
下面例子告诉你如何使用尾闭包形式的map方法来将int数组转换成String数组.数组[16,58,510]是用了创建一下新数组["OneSix", "FiveEight", "FiveOneZero"]:
let digitNames = [
0: "Zero", 1: "One", 2: "Two", 3: "Three", 4: "Four",
5: "Five", 6: "Six", 7: "Seven", 8: "Eight", 9: "Nine"
]
let numbers = [16, 58, 510]
上面代码创建了从数字到英文版本的一个映射字典,它也定义了整型数组,准备用来转换成字符串.
你现在可以使用numbers数组创建一个String数组,通过传递一个闭包表达式作为数组map方法的尾闭包.需要注意的是,调用numbers.map的时候,不需要在map后 面写小括号()了,这是因为map方法只有一个参数,而这个传进来的刚刚好又是尾闭包:
let strings = numbers.map {
(var number) -> String in
var output = ""
while number > 0 {
output = digitNames[number % 10]! + output
number /= 10
}
return output
}
// strings is inferred to be of type String[]
// its value is ["OneSix", "FiveEight", "FiveOneZero"]
map函数调用闭包表达式来处理每个数组中的元素.你不需要指定闭包的输入参数类型,因为具体类型会根据数组中元素的值自动判定.
在这个例子里,闭包的number参数定义为一个可变参数,因此参数的值在闭包内是可以进行修改的,而不用重新声明一个新的局部变量,再给这个局部变量传递number 的值,而且闭包表达式也指定了返回值类型String.
这个闭包表达式每次在被调用的时候,创建一个叫output的字符串,它计算number最后位上的数(通过number%10这个操作),让后用这个数字在字典digitNames中查 找对应的字符串.
注意点:
调用字典的digitNames时候后面跟了一个感叹号!,是因为这个方法返回一个可选值,用来表示如果字典中键不存在的时候,查找失败.在上面的例子里,它保证了 number%10总是合法的健,而且感叹号!会对存储在可选值里的字符串进行强制解包.
从字典digitNames中接收到的字符串被添加到output前面,这样就有效的建立了一个反序的字符串(表达式number%10,会给出16里面的6,58里面的8,510里面的0)
然后变量number除以10,由于它是一个整型,所以结果也是整型,因此16会变成1,58会变成5,510会变成51.
这个过程会一直重复,直到number/=10这个值等于0,这时候output会被闭包返回,然后map函数会将它添加到output数组.
在上面例子里,尾闭包语法的使用,很简洁的封装了闭包功能,不需要在map函数内解包整个闭包.