0Pricing
Swift Academy · 课时

捕获列表——weak/unowned 与值捕获

使用捕获列表控制闭包捕获引用和值的方式:[weak self]、unowned 以及值快照,从而避免保留环和隐蔽的错误。

捕获列表——weak/unowned 与值捕获 是 CoddyKit 上的免费 Swift Academy 课时。 这是第 2 节课,共 3 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Swift Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Swift Academy 课程共包含 3 节课。

为什么使用捕获列表?

目标:控制闭包捕获什么,以及以何种方式捕获。请使用弱引用 self或无主引用来避免引用循环,并在需要时捕获值快照。

强引用捕获 = 循环风险

逃逸闭包或存储型闭包会保留捕获的值。在这里强引用捕获self可能会产生引用循环。

class Owner {
    var name = "Owner"
    var onDone: (() -> Void)?

    func start() {
        // Strong capture of self can cause a cycle if onDone is stored:
        onDone = {
            print("Done by", self.name) // self captured strongly
        }
    }
}
var o: Owner? = Owner()
o?.start()
// If nothing nils onDone or o, both can keep each other alive.

弱引用捕获模式

请使用弱引用 self打破循环。闭包内部的 self 是可选值;请使用守卫式绑定或可选链将其解包。

class Owner2 {
    var name = "Owner2"
    var onDone: (() -> Void)?

    func start() {
        onDone = { [weak self] in
            guard let self = self else { return }  // safely unwrap optional self
            print("Done by", self.name)
        }
    }
}
let o2 = Owner2()
o2.start()
o2.onDone?()

无主引用(谨慎使用)

无主引用假设 self 的生命周期长于闭包(且不是可选值)。只有确定调用时它不可能为 nil 时,才可以使用它。

class Owner3 {
    var onDone: (() -> Void)?
    func work() {
        onDone = { [unowned self] in
            // self must be alive when this runs; otherwise crash
            print("Owner3 still alive")
        }
    }
}
let o3 = Owner3()
o3.work()
o3.onDone?()

值快照的概念

捕获列表可以创建值的快照(例如 [n = count])。没有捕获列表时,其中的常量仍会在创建闭包时被捕获。

var count = 0
let makeLogger: () -> () -> Void = {
    let snapshot = count     // captured by value at creation
    return {
        print("snapshot =", snapshot, "current =", count)
    }
}
count = 10
let logger = makeLogger()
count = 20
logger()   // snapshot = 10, current = 20

捕获列表中的值绑定

请使用捕获列表创建一个命名值快照(例如 [initial = total]),快照会在创建闭包时生成。

var total = 5
let closure = { [initial = total] in
    print("initial:", initial, " now:", total)
}
total = 9
closure()   // initial uses captured value 5

使用弱引用 self 的原因

快速检查:为什么要在存储型或逃逸闭包中添加 [weak self]?

回顾

回顾:使用弱引用 self打破循环(self 会变成可选值),只有在生命周期得到保证时才使用无主引用,并通过捕获列表绑定捕获值快照。

常见问题解答

「捕获列表——weak/unowned 与值捕获」课时是免费的吗?

是的 — 「捕获列表——weak/unowned 与值捕获」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Swift Academy 课程的其余内容,请升级到 CoddyKit PRO。 Swift Academy 课程共包含 3 节课。

「捕获列表——weak/unowned 与值捕获」这节课中我会学到什么?

使用捕获列表控制闭包捕获引用和值的方式:[weak self]、unowned 以及值快照,从而避免保留环和隐蔽的错误。 你通过在浏览器中直接运行的动手代码来练习 Swift Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Swift Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Swift Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 3 节。

「捕获列表——weak/unowned 与值捕获」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Swift Academy 课中编写并运行代码吗?

能。每节 Swift Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 闭包与捕获基础
  2. 捕获列表——weak/unowned 与值捕获
  3. 逃逸与非逃逸闭包、自动闭包
← 返回 Swift Academy