最近在学习RxSwift>>>,大量接触闭包的使用,趁着下班前,翻译了Swift官方文档中闭包那经常使用的一部分,当作复习。
闭包表达式语法
Closure表达式语法具有以下一般形式:
{ (parameters) -> return type in
statements
}
闭包表达式语法中的参数可以是输入参数,但它们不能有默认值。如果命名可变参数,可以使用变量参数。元组也可以用作参数类型和返回类型。
看一个例子:将一个数组排序。之前的做法是:定义一个方法,传入数组,返回排序结果。
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
func backward(_ s1: String, _ s2: String) -> Bool {
return s1 > s2
}
var reversedNames = names.sorted(by: backward)
使用闭包以后:
reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in
return s1 > s2
})
由于闭包的体积非常短,所以它甚至可以写在一行上:
reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in return s1 > s2 } )
从上下文推断类型
因为排序闭包作为参数传递给方法,所以Swift可以推断它的参数类型和它返回的值的类型。排序后的(by :)方法在字符串数组上调用,所以它的参数必须是类型(String,String) - > Bool的函数。这意味着(String,String)和Bool类型不需要作为闭包表达式定义的一部分写入。由于可以推断所有类型,因此也可以省略返回箭头( - >)和参数名称周围的括号:
reversedNames = names.sorted(by: { s1, s2 in return s1 > s2 } )
在将闭包作为内联闭包表达式传递给函数或方法时,始终可以推断参数类型和返回类型。因此,当闭包用作函数或方法参数时,您绝不需要以最充分的形式编写内联闭包。
来自单表达式闭包的隐式返回
通过在声明中省略return关键字,单表达式闭包可隐式返回其单个表达式的结果,如前面示例的此版本所示:
reversedNames = names.sorted(by: { s1, s2 in s1 > s2 } )
这里,排序后的(by :)方法参数的函数类型清楚地表明了闭包必须返回一个Bool值。由于闭包的主体包含一个返回Bool值的单个表达式(s1> s2),因此不存在歧义,并且可以省略return关键字。
速记参数名称
Swift自动为内联闭包提供速记参数名称,这些名称可用于通过名称$ 0,$ 1,$ 2等引用闭包参数的值。
reversedNames = names.sorted(by: { $0 > $1 } )
尾随闭包
如果需要将闭包表达式作为函数的最终参数传递给函数,并且闭包表达式很长,那么将其作为尾部闭包编写可能会很有用。尾随闭包在函数调用的括号后面写入,尽管它仍然是该函数的参数。在使用尾随闭包语法时,不要将闭包的参数标签作为函数调用的一部分写入。
func someFunctionThatTakesAClosure(closure: () -> Void) {
// function body goes here
}
// Here's how you call this function without using a trailing closure:
someFunctionThatTakesAClosure(closure: {
// closure's body goes here
})
// Here's how you call this function with a trailing closure instead:
someFunctionThatTakesAClosure() {
// trailing closure's body goes here
}
上面的Closure Expression Syntax部分中的字符串排序闭包可以在排序的(by :)方法的括号之外写为尾部闭包:
reversedNames = names.sorted() { $0 > $1 }
如果提供闭包表达式作为函数或方法的唯一参数,并且将该表达式作为尾随闭包提供,则在调用该函数时,无需在函数或方法名称后面编写一对括号():
reversedNames = names.sorted { $0 > $1 }
当封闭足够长以至于不可能将它写在一行上时,尾随封闭非常有用。作为一个例子,Swift的数组类型有一个map(_ :)方法,它将一个闭包表达式作为其单个参数。对于数组中的每个项目都调用一次闭包,并为该项目返回一个替代映射值(可能是某种其他类型)。映射的性质和返回值的类型留给闭包来指定。