swift闭包

闭包

闭包表达式的形式

1
2
3
{ (parameters) -> returnType in
statements
}

关键字in表示闭包的参数和返回值类型定义已经完成,闭包函数体即将开始

尾随闭包

当闭包当作最后一个参数传入另一个函数时,可以用尾随闭包来增强可读性。

1
2
3
func closureTest(closure: () -> Void){
closure
}

调用时:

1
2
3
closureTest(){
print("这里是尾随闭包")
}

跟在函数调用后,以大括号包裹的函数体,就是尾随闭包。

逃逸闭包

当一个闭包作为参数传入另一个函数,但是这个闭包在函数执行之后才被执行,这类闭包即是逃逸闭包。逃逸闭包通过在参数名之前标注@escape来表示。

1
2
3
4
var escapingFuncs: [() -> Void] = []
func escapingTest(closure: @escaping () -> Void){
escapingFuncs.append(closure)
}

如上形式就是一个逃逸闭包,如果不加@escaping标注,会得到一个编译错误。

逃逸闭包如果用到self必须显示地声明,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
var escapingFuncs: [() -> Void] = []
func escapingFunc(closure: @escaping () -> Void){
escapingFuncs.append(closure)
}
func withoutEscapingFunc(closure: () -> Void){
closure()
}
class EscapeTest{
var x = 10
func changeX() {
escapingFunc(){
self.x = 100
}
withoutEscapingFunc(){
x = 200
}
}
}
let instance = EscapeTest()
instance.changeX()
print(instance.x) // 200
escapingFuncs.first?()
print(instance.x) // 100

自动闭包

自动闭包是最让我费解的一种。官网一直强调它的延迟执行特点。然而所有的函数都是延迟执行,不去调用函数,只去声明函数,当然不会执行函数体内的语句。这也能算一个特性?我只能理解为,相对于其它闭包来说,这是一个特性😂
官网的例子:

1
2
3
4
5
6
7
8
9
10
11
12
var customersInLine = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
print(customersInLine)
// 打印"5"
let customerProvider = { customersInLine.remove(at: 0) }
print(customersInLine.count)
// 打印"5"
print("Now serving \(customerProvider)")
// 打印 "Now serving Chris!"
print(customersInLine.count)
// 打印"4"

emmm……还是没太明白,这跟直接声明一个函数有什么区别?😂

作为参数传递给函数,参数名前加一个@autoclosure进行标注:

1
2
3
4
5
func serve(customer customerProvider: @autoclosure () -> String){
print("Now serving \(customerProvider())!")
}
serve(customer: customersInLine.remove(at: 0))
// Prints "Now serving Ewa!"

如果没加@autoclosure标注时,传参的地方需要用大括号包裹serve(customer: { customersInLine.remove(at: 0) })。emm….这样对比一下,倒是可以理解延迟加载的意思了。不过感觉还是很鸡肋😂

最后,如果使一个自动闭包也可以逃逸,那就需要两个标注都加上

1
2
3
func serve(customer customerProvider: @autoclosure @escaping() -> String){
`...`
}

简单的记录一下,over!