swift官方文档_关于 Swift 闭包上下文捕获的官方文档导读

c26d45b34cdb7bd5168edaf680b3f382.png

众所周知,闭包的上下文捕获是 Swift 的一大特色,不能不品尝。

8eda469af51c9afdcc2b7c85aaa1a1a0.png
和火锅一样,到了重庆不能不品尝

但很多人,不知为何,总是坚持着一个原则:什么都看,就不看官方文档。

其实官方文档对于闭包及上下文捕获有多处、互见的叙述,比如:

Capturing Values: 闭包捕获(隐式)的简单例子​docs.swift.org Capture List: 显式闭包捕获的用法和原理​docs.swift.org Strong Reference Cycles for Closures: 闭包循环引用​docs.swift.org Escaping Closures: 逃逸闭包​docs.swift.org

第 2 篇中的两个例子最为精彩,分别用显示、隐式的方式,捕获了值类型、引用类型的变量。如果能深入理解一下这两个例子背后的原理,你就能对值类型、引用类型有更好的了解。

我之前将这两例中的第 2 例变形之后,加到了面试题里,结果很多候选人都凉了。
一问才知,在 [] 里,他们只写过 weak self
倘若除了 weak 外,你还知道 unowned self,那也还能及格;不知道的话,至少在 Swift 语言这方面,候选人最高只能是基础水平了。

我们可以先看例 2,再看例 1。

例 2:

class SimpleClass {
    var value: Int = 0
}
var x = SimpleClass()
var y = SimpleClass()
let closure = { [x] in
    print(x.value, y.value)
}

x.value = 10
y.value = 10
closure()
// Prints "10 10"

闭包显式捕获了 x,带来的结果是:若 x 的值发生改变,闭包的运行结果也会改变;而 y 也一样。

关于这个例子,苹果指出:

There are two things named x in the code below, a variable in the outer scope and a constant in the inner scope, but they both refer to the same object because of reference semantics.
下文代码(对我们来说是上例)中,存在两个名叫 x 的东西,一个是闭包外的变量,一个是闭包内的常量,但由于他们是引用类型,所以都指向同一个对象。

当我们「显式」地使用捕获列表 [x] 时,我们「隐式」地声明了一个新的量,一个名为 x 的常量,它的作用域是闭包内。它的显式写法是:

let closure = { [x = x] in
    print(x.value, y.value)
}

或者我们也可以把它写成:

let closure = { [常量X = x] in
    print(常量X.value)
    print(x.value, y.value)
}

因此这里发生了一次声明、赋值的操作。任何的赋值操作,我们都可以认为是一次「复制」

对引用类型来说,你像这样赋值,是复制了一次「x 所指向的对象」的引用,因此,x常量X 就指向了同一个对象;而对于值类型来说,你可以认为,一复制,整个对象就都被复制过去了

再看例 1:

var a = 0
var b = 0
let closure = { [a] in
    print(a, b)
}

a = 10
b = 10
closure()
// Prints "0 10"

由于 [a] 相当于 [a = a],加上 Int 是值类型,所以闭包中的 a 就是对原 a 的复制。所以当外部的 a 发生变化,内部的 a 是不会受影响的。

我们也可以把闭包写成:

let closure = { [aCopy = a] in
    print(aCopy, a, b)
}

这样的话最终就会输出 "0 10 10"

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值