Swift5.0 闭包
2020-03-10 本文已影响0人
Vergil_wj
本文目录:
- 闭包
- 尾随闭包
- 逃逸闭包
- 自动闭包
- 循环引用
闭包
- 全局函数:有名字,不捕获任何值;
- 嵌套函数:有名字,从其封闭函数中捕获值;
- 闭包表达式:无名字,从相邻块中捕获值;
闭包表达式
{ (参数) -> 返回值 in
表达式
}
省略返回值:
{ (参数) in
表达式
}
参数和返回值都省略:
{
表达式
}
闭包类型变量
声明变量为 closure 的闭包:
let closure = {(a:Int,b:Int) -> Int in
return a+b
}
closure(2,3)
尾随闭包
函数最后一个参数是闭包时,可以写为尾随闭包的形式,即可以省略闭包的参数标签,将闭包表达式写在 ()
后面。
函数 add
:
func add(closure:() -> Void){
}
调用函数 add
,不使用尾随闭包的形式:`
add(closure: {
})
调用函数 add
,使用尾随闭包的形式,省略参数标签 closure
:
add() {
}
当闭包是函数的唯一参数是,甚至可以把()
省略:
add {
}
逃逸闭包
在闭包前加@escaping
关键字。
闭包作为一个参数传递给函数,且在函数返回之后才执行,我们称这个闭包从函数中逃逸。一般应用在异步操作的函数中,这类函数会在异步操作开始之后立刻返回,但是闭包直到异步操作结束后才会被调用。
逃逸闭包函数,这样写是为了在函数返回之后再调用闭包:
var closureArray:[() -> Void] = []
func escapingClosure(closure: @escaping () -> Void) {
closureArray.append(closure)
}
非逃逸闭包:
func nonEscapingClosure(closure: () -> Void) {
closure()
}
调用非逃逸闭包函数,x值为100:
var x = 10
nonEscapingClosure {
x = 100
}
print(x) //此时x为100
调用闭包函数,x此时仍为100:
escapingClosure {
x = 200
}
print(x) //此时x仍然为100
因为闭包逃逸,闭包并没有执行,所以代码块中x=200没有执行。下面调用逃逸的闭包,x值变为200:
closureArray.first?()
print(x) //此时x为200
自动闭包
在闭包前加@autoclosure
关键字。
自动闭包就将作为函数参数的表达式自动封装成一个闭包。
先看不使用自动闭包的函数调用:
func isTure(predicate: () -> Bool) {
if predicate() {
print("is ture")
}else{
print("is false")
}
}
调用:
isTure { () -> Bool in
return 2>1
}
再看使用自动闭包的函数的调用:
func isTure(predicate: @autoclosure () -> Bool) {
if predicate() {
print("is ture")
}else{
print("is false")
}
}
调用:
isTure(predicate: 2>1)
自动闭包会在语法上看起来很漂亮。
循环引用
将闭包赋值给类实例的某个属性,并且这个闭包使用了实例,这样会产生强引用环,造成循环引用。
解决循环引用
定义捕获列表:
闭包有参数和返回类型,把捕获列表放在他们前面:
var someClosure = {
[weak self] (index:Int) -> String in
}
闭包没有参数和返回类型,把捕获列表和关键字in
放在闭包最开始的地方:
var someClosure = {
[weak self] in
}