Swift的闭包(二):捕获值
2016-11-08 21:23
218 查看
闭包可以从定义它的上下文中捕获常量和变量。
在Swift中,捕获值最简单的例子是嵌套函数,举个例子:
在这个例子中incrementer()捕获两个值,分别是amount、runningTotal。可以运行一下,观察结果:
注意:如果你把闭包赋值给一个类实例的一个属性,并且闭包通过指向(refer fo)实例或者实例的成员捕获值,那么,在闭包和这个实例间就会有一个强引用环。
把一个闭包标记用@nonescape让你在闭包内隐式的引用(refer to)self,看下这个例子:
Autoclosures可以延迟计算(delay evaluation),因为直到调用闭包时,闭包内的代码才被运行。延迟计算对于有副作用或者计算代价昂贵的代码非常有用,因为你可以控制什么时候代码进行evaluation。
也可以传递给一个参数:
使用@autoclosure:
注意:滥用autoclosure会使代码晦涩难懂。
@autoclosure属性隐含了@nonescape属性,如果你想要一个autoclosure允许esacpe,可以这样使用 @autoclosure(escaping) ,如:
在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!"
相关文章推荐
- 6.7 Swift闭包捕获值
- swift闭包的值捕获
- Swift基础语法: 23 - Swift的Trailing闭包, 捕获, 闭包是引用类型
- Swift-函数式编程、捕获、闭包内存管理
- 二十一 Swift3.0之 闭包捕获值
- swif(六)swift闭包
- 每天学一点Swift----闭包(二)
- swift3 闭包表达式
- Swift 中的闭包循环引用
- Swift - 闭包的介绍及用法(以数组排序为例)
- Swift学习3--函数和闭包
- swift页面传值之block(闭包)传值
- swift 自定义view的写法(内有仿照OC中block的 swift闭包的调用)
- swift swift学习笔记--函数和闭包
- swift3.0下闭包语法汇总
- Swift基础(八)函数和闭包
- Swift的闭包
- Swift 基础学习(闭包)
- [精校版]The Swift Programming Language--语言指南--闭包
- swift-闭包产生的循环引用以及解决办法