Swift的闭包(二):捕获值

更新时间:2023-07-14 15:48:33 阅读: 评论:0

Swift的闭包(⼆):捕获值
闭包可以从定义它的上下⽂中捕获常量和变量。
在Swift中,捕获值最简单的例⼦是嵌套函数,举个例⼦:
1 func makeIncrementer(forIncrement amount: Int) -> () -> Int {
2var runningTotal = 0
3    func incrementer() -> Int {
4        runningTotal += amount
5return runningTotal
6    }
7return 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)lf,看下这个例⼦:
1class SomeClass {
2var x = 10
3    func doSomething() {
4        someFunctionWithNonescapingClosure { x = 200 }
5        someFunctionWithEscapingClosure { lf.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 pasd 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。
1var customersInLine = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
书法家王羲之2 unt)
说唱脸谱歌词3// Prints "5"
4
5 let customerProvider = { ve(at: 0) }
6 unt)
7// Prints "5"
8
9 print("Now rving \(customerProvider())!")
10// Prints "Now rving Chris!"
11 unt)
12// Prints "4"
也可以传递给⼀个参数:
1// customersInLine is ["Alex", "Ewa", "Barry", "Daniella"]
2 func rve(customer customerProvider: () -> String) {
飞字行书
3    print("Now rving \(customerProvider())!")
4 }
5 rve(customer: { ve(at: 0) } )
6// Prints "Now rving Alex!"
使⽤@autoclosure:
1// customersInLine is ["Ewa", "Barry", "Daniella"]
2 func rve(customer customerProvider: @autoclosure () -> String) {
3    print("Now rving \(customerProvider())!")
4 }
5 rve(customer: ve(at: 0))
6// Prints "Now rving Ewa!"
注意:滥⽤autoclosure会使代码晦涩难懂。
@autoclosure属性隐含了@nonescape属性,如果你想要⼀个autoclosure允许esacpe,可以这样使⽤ @autoclosure(escaping) ,如: 1// customersInLine is ["Barry", "Daniella"]
形容结束的词语2var customerProviders: [() -> String] = []
3 func collectCustomerProviders(_ customerProvider: @autoclosure(escaping) () -> String) {
4    customerProviders.append(customerProvider)
5 }
6 ve(at: 0))
7 ve(at: 0))
8
9 print("Collected \(unt) closures.")
10// Prints "Collected 2 closures."
11for customerProvider in customerProviders {
12    print("Now rving \(customerProvider())!")
13 }
14// Prints "Now rving Barry!"
15// Prints "Now rving Daniella!"

本文发布于:2023-07-14 15:48:33,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/89/1081334.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:实例   函数   闭包   参数   代码
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图