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

Swift闭包强引用循环理解及按钮回调场景疑问

你的理解完全正确!先给你吃个定心丸😉

关于Swift闭包强引用循环的理解确认

一、核心逻辑的理解完全没问题

你对闭包引发强引用循环的判断精准命中了核心场景:

  • 当类实例持有闭包类型的属性,同时**闭包内部捕获了该类的self**时,就会形成双向强引用循环:类强引用闭包,闭包强引用类,导致ARC无法释放任何一方,最终造成内存泄漏。
  • 修复方案也完全正确:通过捕获列表[weak self]或[unowned self]打破循环——前者用于self可能比闭包先释放的场景,后者用于两者生命周期完全绑定(self绝不会提前释放)的场景,让闭包对self只持有弱引用/无主引用。

错误示例(会引发强引用循环):

class SomeViewController{ 
    var myClosure: ()->Void! 
    public func someFunction(){ 
        // ....bunch of code 
        myClosure = { 
            self.dismiss(animated: true) 
        } 
    } 
}

修复后的正确示例:

class SomeViewController{ 
    var myClosure: ()->Void! 
    public func someFunction(){ 
        // ....bunch of code 
        myClosure = { [weak self] in 
            self?.dismiss(animated: true) 
        } 
    } 
}

正如Apple文档中提到的:

A strong reference cycle can also occur if you assign a closure to a property of a class instance, and the body of that closure captures the instance

二、按钮回调场景无需[weak self]的判断也正确

你举的按钮回调例子里,完全不需要添加[weak self],原因很直白:

  • 这里的闭包属性someButtonsCallback属于子视图someSubview,而非当前SomeViewController的属性。
  • 此时的引用链是单向的:SomeViewController强引用someSubview → someSubview强引用闭包 → 闭包捕获self(SomeViewController)。这条链没有形成循环,当SomeViewController被释放时,它对someSubview的强引用消失,someSubview和闭包会被ARC正常清理,不会有内存泄漏问题。

你的示例代码:

class SomeViewController { 
    let someSubview: UIView = UIView()
    override func viewDidLoad() { 
        // Some Subview has a button and in that view I just have some action that gets fired off calling the callback here in the view controller 
        someSubview.someButtonsCallback = { 
            // ....run code then 
            self.dismiss(animated: true) 
        } 
    } 
}

当然,如果有极端场景(比如子视图被移到其他父容器中,导致someSubview的生命周期比SomeViewController更长),那闭包里的self可能会变成野指针,这时候才需要[weak self]来避免崩溃,但绝大多数常规的控制器-子视图场景下,完全不用操心。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 06:44:50