闭包表达式语法有如下的一般形式:
{ (parameters) -> returnType in
statements
}
闭包表达式参数 可以是 in-out
参数,但不能设定默认值。也可以使用具名的可变参数(但是如果可变参数不放在参数列表的最后一位的话,调用闭包的时时编译器将报错。)
- 举个例子
var names = ["Jack", "Bob", "Tom", "Alen", "James",]
var sortedArray = names.sorted(by: { (s1: String, s2: String) -> Bool in
return s1 > s2
})
闭包的函数体部分由关键字 in 引入。该关键字表示闭包的参数和返回值类型定义已经完成,闭包函数体即将开始。
简化之旅
根据上下文推断类型
因为排序闭包函数是作为 sorted(by:) 方法的参数传入的,Swift 可以推断其参数和返回值的类型。 sorted(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 } )
sorted(by:) 方法的参数类型明确了闭包必须返回一个 Bool 类型值。因为闭包函数体只包含了一个单一表达式( s1 > s2 ),该表达式返回 Bool 类型值,因此这里没有歧义, return 关键字可以省略。
参数名称缩写
Swift 自动为内联闭包提供了参数名称缩写功能,你可以直接通过$0 , $1 , $2
来顺序调用闭包的参数,以此类推。
如果你在闭包表达式中使用参数名称缩写,你可以在闭包定义中省略参数列表,并且对应参数名称缩写的类型会通过函数类型进行推断。in
关键字也同样可以被省略,因为此时闭包表达式完全由闭包函数体构成:
reversedNames = names.sorted(by: { $0 > $1 } )
在里的$0
和$1
表示闭包中第一个和第二个 String 类型的参数。运算符方法
其实还有一种更简短的方式来编写上面例子中的闭包表达式。Swift 的String
类型定义了关于大于号(>)
的字符串实现,其作为一个函数接受两个String
类型的参数并返回Bool
类型的值。而这正好与
sorted(by:)
方法的参数需要的函数类型相符合。因此,你可以简单地传递一个大于号,Swift 可以自动推断出你想使用大于号的字符串函数实现:
reversedNames = names.sorted(by: >)