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
    
}

参考资料

SwiftGG

上一篇下一篇

猜你喜欢

热点阅读