0Pricing
Swift Academy · 课时

通过引用捕获值

了解闭包如何捕获周围的状态。

通过引用捕获值 是 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 反馈 — 无需本地设置。

此课程中的所有课时

  1. 通过引用捕获值
  2. 逃逸闭包
  3. 捕获列表与弱引用 self
  4. 自动闭包
← 返回 Swift Academy