美文网首页
【Swift】闭包(Closure)

【Swift】闭包(Closure)

作者: 小雪球大梦想 | 来源:发表于2022-12-24 21:59 被阅读0次

    闭包定义

    //函数定义
    func name(parameters) -> return type {
        function body
    }
    
    //闭包定义
    { (parameters) -> return type in
        statements
    }
    

    从上面的函数和闭包的定义中可以看到(parameters) -> return type是相同的,都是传入参数,可对参数进行操作,然后返回一个值。从定义中可以看出,函数是有name的,而闭包没有。

    那么闭包是如何调用的呢?

    //函数
    func area(_ width: Double, _ height: Double) -> Double {
        return width * height
    }
    print(area(3, 4))//打印12.0
    
    //闭包
    let closureArea = { (width: Double, height: Double) -> Double in
        width * height//单行表达式,因为只有一行表达式,所以return可以不写
    }
    print(closureArea(3, 4))//打印12.0
    

    函数中给这个求面积的函数命名为area,而闭包是用{}包裹起来,在这里闭包是没有名字的,所以将闭包赋值相当于给闭包一个名字closureArea,这样闭包就能像函数一样使用。所以area约等于closureArea

    闭包是特殊的函数,当函数作为参数,或返回值,或匿名函数时,称为闭包。

    // 为参数,(Double, Double) -> Double为闭包
    func area(handle: (Double, Double) -> Double) -> Double {
        return handle(3, 4)
    }
    print(area(handle: {$0 * $1}))//打印12.0
    

    area函数看到,函数中只传入一个闭包,然后返回一个Double值。函数返回值是执行闭包返回的结果,闭包传入(3, 4)

    闭包对参数做了什么?在调用area函数时,需要将闭包传入,这里是传入{$0 * $1}闭包,对参数执行乘法运算。

    // 为返回值
    func area() -> (Double, Double) -> Double {
        return { $0 * $1 }
    }
    print(area()(3, 4))//打印12.0
    

    area函数看到,函数中没有传入参数,只有返回一个闭包(Double, Double) -> Double,闭包执行了第一个和第二个参数的乘法运算,所以area()就是一个闭包。

    (3, 4)是闭包传入的参数,所以结果为12.0

    // 为匿名函数
    let areaValue = { (width: Double, height: Double) -> Double in
        return width * height
    }(3, 4)
    print(areaValue)//打印12.0
    

    { (width: Double, height: Double) -> Double in return width * height }是一个闭包,这里我们没有把闭包赋值给一个对象,而是直接使用闭包。直接将(3, 4)传入闭包,所以这个闭包是一个没有名字的闭包,称匿名闭包。

    最简闭包

    单行表达式,隐式返回值,return可以不写。

    简化参数

    $0$1,代表第01个参数。

    // 闭包
    { (width: Double, height: Double) -> Double in
        return width * height
    }
    
    // 最简闭包,简化参数
    { $0 * $1 }
    

    尾随闭包

    闭包是函数的最后一个参数,称为尾随闭包。

    func area(width: Double, height: Double ,handle: (Double, Double) -> Double) -> Double {
        return handle(width, height)
    }
    print(area(width: 3, height: 4, handle: {$0 * $1}))//打印12.0
    

    area函数中可以看到,函数中有widthheight(Double, Double) -> Double三个参数,返回一个Double值。

    从函数中的handle(width, height)中,我们可以看到widthheight作为参数传到handle这个闭包里面,闭包根据传值做了一个处理然后返回一个Double值,具体要对widthheight做什么处理,需要将闭包作为参数传入area函数中进行处理。

    在例子中,传入了闭包{$0 * $1},这个闭包的意思是对传入的第一个和第二个参数做乘法运算,所以打印的结果就是3 * 4,计算结果12.0

    //尾随闭包写法
    let value1 = area(width: 3, height: 4, handle: {$0 * $1})
    // 简化
    let value2 = area(width: 3, height: 4) { $0 * $1 }
    print(value1, value2)//打印12.0 12.0
    

    自动闭包

    自动闭包是一种自动创建的闭包,用于包装传递给函数作为参数的表达式。
    这种闭包不接受任何参数,当它被调用的时候,会返回被包装在其中的表达式的值。
    这种便利语法让你能够省略闭包的花括号{},用一个普通的表达式来代替显式的闭包。

    // 闭包
    func closure(_ closure: () -> String) {
        print("closure \(closure())")
    }
    
    closure({ "value1!" })
    closure { "value2!" }
    
    // 自动闭包
    func autoClosure(_ closure: @autoclosure () -> String) {
        print("autoClosure \(closure())")
    }
    
    autoClosure("v3!")
    

    逃逸闭包

    一个接受闭包作为参数的函数,该闭包可能在函数返回后才被调用,也就是说这个闭包逃离了函数的作用域,这种闭包称为逃逸闭包。当你声明一个接受闭包作为形式参数的函数时,你可以在形式参数前写@escaping来明确闭包式允许逃逸,并且在闭包中显式地引用self

    逃逸闭包的生命周期

    1. 闭包作为参数传入函数。
    2. 退出函数。
    3. 闭包被调用,闭包生命周期结束。

    逃逸闭包的生命周期比函数长,函数退出时,逃逸闭包的引用仍被其他对象持有,不会在函数结束时释放。

    var array: Array<() -> String> = []
    
    func appendClosure(_ closure: @autoclosure @escaping () -> String) {
        array.append(closure)
    }
    
    appendClosure("Hello")
    let closure = array.first!
    print(closure())// 打印 Hello
    

    appendClosure函数看出,() -> String闭包传入到appendClosure函数中,函数引用了闭包,并将闭包保存到了数组中。退出函数后,闭包还没被调用,所以这个时候闭包就逃逸了。

    相关文章

      网友评论

          本文标题:【Swift】闭包(Closure)

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