闭包简介
什么是Closures
? Closures
也就是我们常说的闭包,闭包是一个具有函数功能的代码块,它类似于OC中的Block
,它能够在它被定义的上下文中,被常量或者变量所捕捉和存储。也就是是说把常量和变量Closing
(包)住了,这也是Closures
的由来。全局函数和嵌套函数(Global and nested functions
)是闭包的一种特例,闭包有一下三种形式:
- 全局函数是有名称但是不会捕获任何数值得闭包。
- 嵌套函数是有名称并且可以从它们的封闭的函数体内部捕获数值的闭包。
- 闭包表达式是用轻量级的语言所书写,并且能够从它们所在的上下文中获取数值的一种没有名称的closures。
由于Swift本身对闭包做了很多的优化,这使得闭包的使用更加的简单明了,这些优化包括:
- 从上下文中推断出参数类型和返回值类型
- 在单一表达的闭包(
single-expression
)中隐含返回值 - 简化参数名
- 尾随闭包语法
闭包的基本语法
1 | //闭包表达式的类型和函数的类型是一样的,都是参数加上返回值,但是闭包后面有一个in, 这个关键字来告诉编译器,闭包的参数和返回值已经定义完了,下面是闭包执行语句了。 |
下面说明闭包的基本用法:
- 闭包的完整写法:
1 | // 闭包的完整写法 |
- 没有返回值得闭包
1 | // 由于这个闭包没有返回值,所以Void可以省略 |
- 没有参数没有返回值得闭包
1 | // 没有参数没有返回值的写法 |
- 闭包做为一个参数
1 | // 闭包做为一个参数 |
- 闭包做为函数的返回值
1 |
|
- 捕获值,(在闭包内部捕获闭包所在的上下文(
surrounding context
)的变量)
1 | // 捕获值(这里也是一个以闭包做为返回值的函数) |
- 尾随闭包
Trailing Closures
:如果闭包是函数的最后一个参数,并且闭包比较长,这个时候可以在()的后面写一个{}来做为闭包。上文提到的functionToRunClosureAsParam()就是这样一个例子,所以我们可以使用尾随闭包来简化函数的调用。
1 | //闭包做为函数的最后一个参数 |
闭包的高级用法
Noescape Closures
:非逃逸型闭包,如果闭包是函数的一个参数,那么这个闭包只能在函数内部使用;Escape Closures
:逃逸型闭包,当闭包做为函数的一个参数的时候,有时候在函数已经执行完,并且已经返回,但是这之后才调用闭包,这种闭包就称为逃逸闭包(Escaping Closure),逃逸型闭包可以用在异步操作。
1 | // 非逃逸型闭包 |
下面在举个例子说明Noescape Closures
的用法:
1 | // 再比如非逃逸型闭包 |
Autoclosures
自动闭包:如果函数中的一个闭包参数被@autoclosures
修饰,那么这个函数在被调用的时候可以省去花括号,注意如果一个闭包被autoClosures修饰的时候默认是noescape型的,所以在不能用到异步处理中,这是只需要在将@autoclosure
变为@autoclosure(escaping)
就可以了
下面举例说明:
1 | // customersInLine is ["Ewa", "Barry", "Daniella"] |