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

iOS中VC被弹出导航栈后是否短暂存活?定时器崩溃排查

问题诊断与修复方案

核心原因验证

你的怀疑完全正确——NSTimer会强持有目标对象。如果你的SwiftSimpleScheduler里的NSTimer把SKScene(或关联的VC)作为target,那么即便VC被弹出导航栈,NSTimer的强引用会死死攥住对象不让它释放,定时器自然会继续触发。这时候CURRENT_GAME_VC从导航栈里找不到对应实例返回nil,强制解包直接触发崩溃。

具体修复步骤

1. 给定时器加上弱引用,切断强持有链

NSTimer默认强引用target,改用block形式的初始化方法,在block里捕获weak引用的self,这样对象释放时能自动终止定时器:

// 替换原有NSTimer创建代码
Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { [weak self, weak scheduler] timer in
    guard let self = self, let scheduler = scheduler else {
        timer.invalidate()
        return
    }
    self.onTick()
}

当self(SKScene/VC)被释放时,weak引用会变成nil,此时立即销毁定时器,从根源上避免无效触发。

2. 干掉强制解包,加安全校验

强制解包是崩溃的直接导火索,不管定时器问题是否解决,都必须给CURRENT_GAME_VC加安全访问逻辑:

// 替换原来的强制解包代码
guard let gameVC = CURRENT_GAME_VC else {
    // 做降级处理:停止调度器、打日志都可以
    scheduler.stopAllTasks()
    return
}
// 再正常使用gameVC

3. 主动在VC销毁时终止定时器

在VC的deinit方法里主动调用调度器的销毁逻辑,同时打印日志确认对象是否真的被释放:

deinit {
    scheduler.invalidateAllTimers() // 假设调度器提供这个方法
    print("GameVC/SKScene 已释放")
}

如果日志没打印,说明还有其他强引用(比如闭包没捕获weak、代理没设为weak),得进一步排查。

额外排查方向

  • 检查CURRENT_GAME_VC的实现:是否在VC弹出后,导航栈的viewControllers数组没及时更新?可以在onTick里打印数组内容,确认是否真的没有GameVC实例。
  • 确认调度器的生命周期:如果SwiftSimpleScheduler是全局对象或被其他强引用持有,就算VC释放了,调度器还活着,定时器也会继续跑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 22:23:20