You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

当前ViewController与ViewModel代码是否产生强引用循环?weak还是unowned?

强引用循环分析 & 解决方案

好问题!咱们来仔细拆解你的代码,看看是否存在强引用循环,以及对应的处理方式:

1. 当前代码是否存在强引用循环?

答案是:不存在。我们来梳理一下引用关系:

  • ViewController 持有一个强引用的 viewModel 属性:var viewModel = ViewModel()
  • ViewModel 的 showAlert 是一个可选闭包,你在 viewDidLoad 中给它赋值时,使用了 [weak self] 捕获了 ViewController 的弱引用

此时的引用链是:ViewController → 强引用 → ViewModel,而闭包对 ViewController 的引用是弱引用,不会形成「互相强引用」的闭环,所以不会产生内存泄漏。

如果去掉 [weak self],情况就不一样了:闭包会强引用 ViewController,加上 ViewController 本身强引用 ViewModel,就会形成 ViewController ↔️ ViewModel 的强引用循环,导致两者都无法被系统释放,造成内存泄漏。

2. 若存在强引用循环,该用 weak 还是 unowned?

这取决于被捕获对象(也就是这里的 ViewController)是否可能在闭包执行期间变为 nil:

  • 用 weak:当被捕获对象可能被释放(比如 ViewController 可能被从导航栈弹出、或者被销毁)时,weak 是更安全的选择。它会自动将引用置为 nil,避免野指针访问。你的场景里,ViewController 作为UI控制器,显然存在被释放的可能,所以 weak 是正确的选择。
  • 用 unowned:只有当你能100%确定被捕获对象在闭包执行期间永远不会被释放时,才考虑使用 unowned。它不会自动置为 nil,如果对象被释放后访问,会直接触发运行时崩溃。比如一个对象的闭包是该对象的一部分,且两者生命周期完全绑定的场景。

补充代码示例(正确的弱引用写法)

你的代码已经是正确的写法了,再贴一遍方便对照:

class ViewController { 
    var viewModel = ViewModel() 
    func viewDidLoad() { 
        self.viewModel.showAlert = { [weak self] in 
            self?.alert() 
        } 
    } 
    func alert() { 
        // alert logic 
    } 
}

class ViewModel { 
    var showAlert: (() -> Void)? 
}

内容的提问来源于stack exchange,提问作者Savan Kavaiya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:25:47