通过引用捕获值
了解闭包如何捕获周围的状态。
通过引用捕获值 是 CoddyKit 上的免费 Swift Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Swift Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Swift Academy 课程共包含 4 节课。
闭包捕获的内容
闭包会捕获它所引用的周围作用域中的变量和常量。被捕获的变量会按引用持有,因此闭包能够看到之后发生的更改。
捕获常量
即使函数已经返回,闭包仍会记住 greeting:
func makeGreeter() -> () -> String {
let greeting = "Hello"
return { greeting }
}
let greet = makeGreeter()
print(greet()) // "Hello"按引用捕获变量
由于 count 是变量,闭包会在多次调用之间修改同一份存储空间:
func makeCounter() -> () -> Int {
var count = 0
return {
count += 1
return count
}
}
let next = makeCounter()
print(next(), next(), next()) // 1 2 3共享存储空间
两个闭包可以捕获同一个变量,并看到彼此对它所做的更改:
func makePair() -> (() -> Void, () -> Int) {
var value = 0
let inc = { value += 1 }
let read = { value }
return (inc, read)
}
let (inc, read) = makePair()
inc(); inc()
print(read()) // 2捕获会反映之后的更改
闭包会在调用时读取变量的当前值,而不是闭包创建时的值:
var message = "first"
let show = { print(message) }
message = "second"
show() // "second"按引用捕获与按值捕获
默认情况下,可变变量会按引用捕获。如果您希望在创建时冻结其值的副本,请将它列入捕获列表,例如 [x]。
冻结值
捕获列表会立即复制该值:
var n = 10
let frozen = { [n] in n } // copies 10 now
n = 99
print(frozen()) // 10每个闭包拥有独立状态
工厂的每次调用都会创建一个全新的被捕获变量:
func counter() -> () -> Int {
var c = 0
return { c += 1; return c }
}
let a = counter(), b = counter()
print(a(), a(), b()) // 1 2 1在循环中捕获
如果不加注意,循环中的闭包可能会共享同一个变量。请使用捕获列表,为每次迭代创建快照:
var closures: [() -> Int] = []
for i in 1...3 {
closures.append { [i] in i }
}
print(closures.map { $0() }) // [1, 2, 3]在方法中捕获 self
在方法内部创建的闭包会捕获周围的实例,使其之后能够读取和修改属性:
class Bank {
var balance = 0
func deposit() -> () -> Void {
return { self.balance += 10 }
}
}
let bank = Bank()
let add = bank.deposit()
add(); add()
print(bank.balance) // 20为什么这很重要
按引用捕获为计数器、累加器和有状态回调提供了支持 — 但这也意味着闭包可能让对象持续存活。接下来我们会使用捕获列表来管理这一点。
func accumulator() -> (Int) -> Int {
var total = 0
return { total += $0; return total }
}
let add = accumulator()
print(add(10), add(5)) // 10 15快速检查
默认情况下,闭包会如何捕获可变变量?
回顾
您已经了解了捕获语义:
- 闭包会从其作用域中捕获被引用的变量
- 可变变量会按引用捕获 — 更改和修改会被共享
- 捕获列表
[x]会在创建时冻结一个值的副本 - 这为计数器和有状态回调提供了支持
下一步:逃逸闭包。
常见问题解答
「通过引用捕获值」课时是免费的吗?
是的 — 「通过引用捕获值」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Swift Academy 课程的其余内容,请升级到 CoddyKit PRO。 Swift Academy 课程共包含 4 节课。
「通过引用捕获值」这节课中我会学到什么?
了解闭包如何捕获周围的状态。 你通过在浏览器中直接运行的动手代码来练习 Swift Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Swift Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Swift Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。
「通过引用捕获值」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Swift Academy 课中编写并运行代码吗?
能。每节 Swift Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 通过引用捕获值
- 逃逸闭包
- 捕获列表与弱引用 self
- 自动闭包