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

通过闭包传递并返回self替代[weak self],是否会产生循环引用?

这个写法会产生循环引用吗?

好问题!咱们来拆解一下你的代码逻辑,看看循环引用是怎么形成的:

为什么当前写法会有循环引用风险?

循环引用的核心是两个对象互相强引用,导致都无法被系统回收。结合你的代码来看:

  1. 假设调用askToConfirm(from: self)的那个 ViewController(也就是代码里的self),对alertManager持有强引用(比如把它作为类属性)。
  2. 在AlertManager的askToConfirm方法中,你创建的invitation对象会持有那个带[weak self]的闭包。
  3. 这个闭包会强引用传入的vc(也就是你的 ViewController),同时还会强引用调用者传入的completion闭包——而你的completion闭包里又用到了vc(比如vc.model.confirm()),相当于completion也强引用了 ViewController。
  4. 最终形成的引用链是:ViewController → alertManager → invitation → 闭包 → ViewController(或者加上completion的链路),这就形成了闭环,导致两者都无法被释放,造成内存泄漏。

怎么修改才能避免?

你想要避免在调用处写[weak self]的需求是合理的,只需要在AlertManager的闭包里,对传入的vc也做弱引用处理即可:

func askToConfirm<T>(from vc: T, completion: @escaping (T, Bool) -> ()) {
    // 这里给vc加上weak修饰
    let invitation = pageItemFactory.createConfirmationPageItem() { [weak self, weak vc] accepted in
        self?.dismissAlert()
        // 先判断vc是否还存在,再执行completion
        guard let safeVC = vc else { return }
        completion(safeVC, accepted)
    }
    present(invitation)
}

这样修改后,闭包里只持有vc的弱引用,不会再形成循环,同时调用处依然不需要写[weak self],完美满足你的需求。

另外要额外注意:如果alertManager是单例,这个问题会更严重——单例的生命周期和APP一致,强引用的ViewController永远不会被回收,内存泄漏会一直存在,所以这种场景下弱引用vc就更必要了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 07:57:39