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

手动构造的UIViewController内存泄漏无法被Debug Memory Graph检测是什么原因?

根因分析

你构造的UIViewController自循环泄漏是真实存在的,Debug Memory Graph漏检是UIKit特性和工具检测逻辑共同导致的,普通对象没有UIKit的内部缓存机制,所以不会出现这类问题:

  • UIKit内部对UIViewController有临时引用缓存,调用dismiss后系统不会立刻清理控制器的内部关联引用,会延迟到下几个RunLoop周期、页面动画完全结束、视图层级彻底移除后才会释放内部缓存。如果刚dismiss就打开Debug Memory Graph,此时控制器同时被obj = self循环引用+UIKit临时引用持有,工具会误判为控制器仍被系统正常使用,不会标记为泄漏。
  • Debug Memory Graph默认开启了系统引用过滤规则,会自动隐藏UIKit内部的引用链,同时会优先过滤掉它判定为「系统正常持有」的对象,漏检自定义的循环引用。

验证&修复检测问题的方法

  • 你可以在Demo类中添加deinit方法打印日志,会发现dismiss后deinit永远不会执行,证明泄漏真实存在,和工具检测结果无关。
  • 要让Debug Memory Graph正常识别泄漏,可以在dismiss后等待3~5秒,或触发几次界面交互,等UIKit内部缓存释放后再打开检测工具即可。
  • 也可以使用Instruments中的Leaks工具检测,该工具对循环引用的识别敏感度更高,不会出现这类漏检情况。

你提供的测试代码参考:

import UIKit
class ViewController: UIViewController {
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        present(Demo(), animated: true, completion: nil)
    }
}
class Demo : UIViewController {
    var obj:Demo?
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .systemTeal
        obj = self
    }
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        dismiss(animated: true, completion: nil)
    }
}

相关问题截图:
问题相关截图

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 13:24:03