美文网首页
Swift5.0 闭包

Swift5.0 闭包

作者: Vergil_wj | 来源:发表于2020-03-10 14:45 被阅读0次

    本文目录:

    • 闭包
    • 尾随闭包
    • 逃逸闭包
    • 自动闭包
    • 循环引用

    闭包

    • 全局函数:有名字,不捕获任何值;
    • 嵌套函数:有名字,从其封闭函数中捕获值;
    • 闭包表达式:无名字,从相邻块中捕获值;

    闭包表达式

    { (参数) -> 返回值 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

    相关文章

      网友评论

          本文标题:Swift5.0 闭包

          本文链接:https://www.haomeiwen.com/subject/uomwdhtx.html