闭包在Swift中很是有用。通俗的解释就是一个Int类型里存储着一个整数,一个String类型包含着一串字符,一样,闭包是一个包含着函数的类型。有了闭包,你就能够处理不少在一些古老的语言中不能处理的事情。这是由于闭包使用的多样性,好比你能够将闭包赋值给一个变量,你也能够将闭包做为一个函数的参数,你甚至能够将闭包做为一个函数的返回值。它的强大之处可见一斑。express
在Swift的不少文档教材中都说函数是“一等公民”,起初我还不是很理解“一等公民”是什么意思,但当我理解了闭包以及它的强大功能后,我恍然大悟、茅塞顿开、醍醐灌顶。原来闭包的这些特性就是“一等公民”的特性啊!参见维基百科First-class citizen。swift
Swift中的闭包相似Objective-C中的Block。其实,若是你想在Swift中实现Objective-C里的Block功能,你能够直接使用闭包来代替。Block和闭包的区别只是语法的不一样而已,并且闭包的可读性比较强。数组
函数是闭包吗?闭包
虽然你尚未意识到,但咱们确实已经在Swift中这么用了。Swift中的函数就是闭包,在Apple的官方文档中有这样的描述:函数
闭包有三种形式:spa
1. 全局函数是一个有名字但不会捕获任何值的闭包。orm
2. 嵌套函数是一个有名字并能够捕获到其封闭函数域内的值的闭包。ip
3. 闭包表达式是一个利用轻量级语法所写的,能够捕获其上下文中变量或常量值的匿名闭包。ci
今天,咱们要讨论的是第三种形式,尤为讨论它是如何将繁复的、可读性比较差的业务逻辑代码压缩成高可读性、简明明了的形式。文档
你们还记得数组的map方法么?它的参数就是一个闭包,它会将数组里的每个元素放在闭包中进行处理,而后返回一个新的数组,甚至是与原数组不一样元素类型的新数组。
map函数的原型以下:
func map<U>(transform: (T) -> U) -> [U]
咱们能够看到该函数使用了泛型。(T) -> U是一个泛型闭包,它的意思就是类型T将会在闭包中进行逻辑处理,而后返回U类型。最后map函数会返回一个U类型的数组。
用一个例子来讲明。今天我办生日聚会,要迎接不少人,而且为每一个人都准备了一句欢迎词。咱们要怎么作呢?首先咱们将迎接的人放进一个数组名叫guestList,而后用一个名叫greetPeople的函数为每一个人生成欢迎词:
func greetPeople(person: String) -> String
{
return "Hello, \(person)!"
}
let guestList = ["Chris", "Jill", "Tim"]
let fullGreetings = guestList.map(greetPeople)
而后将greetPeople函数做为guestList数组的map函数的参数传入,并返回一个新的数组fullGreetings,这个数组就包含了每一个人的欢迎词。
若是咱们想展现一下每一个人的欢迎词,咱们甚至能够这样写:
fullGreetings.map(println)
这时也许有人要质疑了,println函数不是没有返回值么?那么map函数会返回什么呢?其实每个没有返回值的函数,都会返回一个空的元组(tuple),因此说上述代码的返回值实际上是Array<()>。
上面的例子中咱们就是将一个全局函数greetPeople做为一个闭包来使用的。
简明扼要的闭包表达式
其实Swift已经为咱们提供了不少简化的语法,可让咱们保证代码的高可读性和维护性。还用上面的例子来讲明,对于greetPeople这个全局函数来讲,其实只须要使用一次,因此咱们不必单独定义这个函数。咱们能够直接使用闭包表达式来处理:
let fullGreetings = guestList.map({(person: String) -> String in return "Hello, \(person)!"})
闭包表达式实际上是函数的字面值,官方通常称之为匿名函数。通常当咱们须要使用函数快速的实现一个简短的处理逻辑而且只使用一次的时候,咱们能够省去函数名,使用简化的语法。上面的代码中能够看到关键字in以前是闭包表达式的参数和返回值,in以后是闭包表达式实际处理逻辑的代码区域。
下面咱们将使用Swift更多的特性来进一步简化闭包表达式。
咱们知道Swift中有类型推断的特性,因此咱们能够取掉参数类型:
let fullGreetings = guestList.map({(person) -> String in return "Hello, \(person)!" })
像咱们示例中的这种单一闭包表达式,编译器能够根据in以前的返回值类型和return以后的返回数据类型自动判断,因此咱们能够省略返回值和return关键字:
let fullGreetings = guestList.map({person in "Hello, \(person)!" })
其实在Swift中还提供了参数的简写方式:$0表明第一个参数、$1表明第二个参数以此类推。因此咱们又能够将参数名称省略:
let fullGreetings = guestList.map({ "Hello, \($0)!" })
当函数的最后一个参数是闭包时,能够将闭包写在()以外,这也是Swift的一个特性,因此咱们还能够继续简化:
let fullGreetings = guestList.map(){ "Hello, \($0)!" }
当函数有且仅有一个参数,并该参数是闭包时,不但能够将闭包写在()外,还能够省略():
let fullGreetings = guestList.map{ "Hello, \($0)!" }
到目前为止,示例中的闭包表达式已经被咱们根据Swift的特性,简化为简明扼要、高可读性的闭包表达式了,是否是很酷呢!