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

含计时器的UIView类及关联类无法触发deinit问题咨询

问题分析与解决方案

咱们先直接戳中核心:这两个类的deinit无法被调用,本质是内存泄漏导致的,主要来自两个关键错误,咱们一步步拆解修复:

1. 第一个致命错误:layoutSubviews里重复创建实例

layoutSubviews是个会被频繁触发的方法(比如视图尺寸变化、父视图布局更新时都会调用),你现在每次调用都新建一个NextView并赋值给nextView——旧的NextView实例虽然失去了MyView的强引用,但如果它自身还有其他强引用(比如Timer),就会直接变成内存垃圾,永远无法释放。

2. 第二个循环引用陷阱

你在Timer的block里用了[weak self]看似没问题,但NextView的deinit逻辑写反了:你先打印再去invalidate Timer。而Timer被创建后会被RunLoop强引用,只有调用invalidate才能让RunLoop释放它。现在的情况是:

  • NextView持有Timer,RunLoop持有Timer,导致NextView的引用计数永远降不到0,deinit根本没机会执行;
  • MyView又强引用着NextView,连锁导致MyView也无法被释放。

修复方案

第一步:修正layoutSubviews的创建逻辑

只在nextView为空时创建实例,避免重复创建导致的内存泄漏:

class MyView: UIView { 
    var nextView: NextView? 
    override func layoutSubviews() { 
        super.layoutSubviews() 
        // 仅在nextView未初始化时创建实例
        guard nextView == nil else { return }
        nextView = NextView() 
        nextView!.go() 
    } 
    deinit { print("MyView deinit: call me") } 
} 

第二步:修正NextView的Timer生命周期管理

必须在deinit执行前先让RunLoop释放Timer,同时避免重复创建Timer:

class NextView { 
    var timer: Timer? 
    func go() { 
        // 创建新Timer前先销毁旧的,避免重复调度
        timer?.invalidate()
        timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true, block: { [weak self] _ in 
            // 这里添加Timer的具体执行逻辑
        }) 
    } 
    deinit { 
        // 先让RunLoop释放Timer,再执行其他操作
        timer?.invalidate() 
        timer = nil 
        print("NextView deinit: call me") 
    } 
}

第三步:确保MyView的引用被正确释放

当你不再需要MyView时,要主动将持有它的变量置为nil(比如在ViewController中):

// 示例:在ViewController中持有MyView
var myView: MyView? = MyView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
// 当不需要时释放引用
myView = nil

修复原理

  • 修正layoutSubviews后,避免了重复创建NextView导致的旧实例泄漏;
  • 提前invalidate Timer,让RunLoop释放对Timer的强引用,NextView的引用计数能正常降到0,deinit得以执行;
  • NextView正常释放后,MyView的nextView引用也会被释放,MyView的deinit就能正常触发。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:33:52