• Swift的闭包(二):捕获值


    闭包可以从定义它的上下文中捕获常量和变量。

    在Swift中,捕获值最简单的例子是嵌套函数,举个例子:

    1 func makeIncrementer(forIncrement amount: Int) -> () -> Int {
    2     var runningTotal = 0
    3     func incrementer() -> Int {
    4         runningTotal += amount
    5         return runningTotal
    6     }
    7     return incrementer
    8 }

    在这个例子中incrementer()捕获两个值,分别是amount、runningTotal。可以运行一下,观察结果:

    1 let incrementByTen = makeIncrementer(forIncrement: 10)
    2 print(incrementByTen())     //10
    3 print(incrementByTen())     //20
    4 let incrementByNine = makeIncrementer(forIncrement: 9) 5 print(incrementByNine()) //9 6 print(incrementByNine()) //18
    7 print(incrementByTen()) //30

    注意:如果你把闭包赋值给一个类实例的一个属性,并且闭包通过指向(refer fo)实例或者实例的成员捕获值,那么,在闭包和这个实例间就会有一个强引用环。

    闭包是引用类型(Reference Types)

    闭包和函数都是引用类型。

    Nonescaping Closures

    当一个闭包作为参数传递给一个函数,但是在函数返回后调用的时候,我们说一个闭包是escaped的。当你声明一个有一个闭包作为参数的函数的时候,你可以在参数类型前写@nonescape来暗示这个closure不允许escape。如:

    1 func someFunctionWithNonescapingClosure(closure: @noescape () -> Void) {
    2     closure()
    3 }

    把一个闭包标记用@nonescape让你在闭包内隐式的引用(refer to)self,看下这个例子:

     1 class SomeClass {
     2     var x = 10
     3     func doSomething() {
     4         someFunctionWithNonescapingClosure { x = 200 }
     5         someFunctionWithEscapingClosure { self.x = 100 }
     6     }
     7 }
     8  
     9 let instance = SomeClass()
    10 instance.doSomething()
    11 print(instance.x)
    12 // Prints "200"
    13  
    14 completionHandlers.first?()
    15 print(instance.x)
    16 // Prints "100"

    Autoclosures

    An autoclosure is a closure that is automatically created to wrap an expression that's being passed as an argument to a function. It doesn't take any arguments, and when it's called, it returns the value of the expression that's wrapped inside of it.

    Autoclosures可以延迟计算(delay evaluation),因为直到调用闭包时,闭包内的代码才被运行。延迟计算对于有副作用或者计算代价昂贵的代码非常有用,因为你可以控制什么时候代码进行evaluation。

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

    也可以传递给一个参数:

    1 // customersInLine is ["Alex", "Ewa", "Barry", "Daniella"]
    2 func serve(customer customerProvider: () -> String) {
    3     print("Now serving (customerProvider())!")
    4 }
    5 serve(customer: { customersInLine.remove(at: 0) } )
    6 // Prints "Now serving Alex!"

    使用@autoclosure:

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

    注意:滥用autoclosure会使代码晦涩难懂。

    @autoclosure属性隐含了@nonescape属性,如果你想要一个autoclosure允许esacpe,可以这样使用 @autoclosure(escaping) ,如:

     1 // customersInLine is ["Barry", "Daniella"]
     2 var customerProviders: [() -> String] = []
     3 func collectCustomerProviders(_ customerProvider: @autoclosure(escaping) () -> String) {
     4     customerProviders.append(customerProvider)
     5 }
     6 collectCustomerProviders(customersInLine.remove(at: 0))
     7 collectCustomerProviders(customersInLine.remove(at: 0))
     8  
     9 print("Collected (customerProviders.count) closures.")
    10 // Prints "Collected 2 closures."
    11 for customerProvider in customerProviders {
    12     print("Now serving (customerProvider())!")
    13 }
    14 // Prints "Now serving Barry!"
    15 // Prints "Now serving Daniella!"
  • 相关阅读:
    css中优先级与层叠
    微服务通过feign.RequestInterceptor传递参数
    maven详解
    Java8新特性interface中的static方法和default方法
    设计模式六大原则---转
    MySQL主从复制作用和原理
    Mysql Binlog三种格式详细介绍
    分布式主键生成逻辑总结--转
    java幂等性的解决方案
    spring事务的传播机制新解
  • 原文地址:https://www.cnblogs.com/xjshi/p/6044701.html
Copyright © 2020-2023  润新知