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

如何在ViewDidLoad外失效Timer?声明全局Timer触发SIGABRT错误求助

Fixing Your Timer SIGABRT Crash & Invalidation Issues

Let's break down what's happening with your Timer code, and how to fix both the "Timer失效" issue and the subsequent SIGABRT crash:

First: Why Your Original Local Timer Was "失效"

In your viewDidAppear method, you're creating a local Timer variable. As soon as the method finishes executing, ARC (Automatic Reference Counting) releases this Timer instance because there are no strong references keeping it alive. That's why it stops working after the first fire—there's no Timer left to repeat the task.

Second: Why the Global/Instance Timer Causes SIGABRT

When you move the Timer to a global or instance variable, you create a strong reference cycle (循环引用):

  • The Timer holds a strong reference to its target (your ViewController)
  • Your ViewController holds a strong reference to the Timer (via the global/instance variable)

Neither object can be properly deallocated when your ViewController is dismissed or popped. This leads to memory leaks, and eventually triggers a SIGABRT crash when the system tries to clean up these stuck objects.

The Fixes

Here are two reliable solutions, depending on whether you prefer block-based or selector-based Timer usage:

First, declare an optional Timer instance variable in your ViewController:

private var updateTimer: Timer?

Then, create the Timer in viewDidAppear with a weak reference to self to break the cycle:

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated) // Don't forget to call super!
    updateTimer = Timer.scheduledTimer(withTimeInterval: 3, repeats: true) { [weak self] _ in
        self?.updateOnlineTrack()
    }
}

Finally, clean up the Timer when the ViewController disappears to avoid leaks:

override func viewDidDisappear(_ animated: Bool) {
    super.viewDidDisappear(animated)
    updateTimer?.invalidate()
    updateTimer = nil // Explicitly break the reference
}

Solution 2: Selector-Based Timer (If You Prefer This Style)

Again, start with an optional instance variable:

private var updateTimer: Timer?

Update your viewDidAppear method (and don't forget super):

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    updateTimer = Timer(timeInterval: 3, target: self, selector: #selector(updateOnlineTrack), userInfo: nil, repeats: true)
    RunLoop.current.add(updateTimer!, forMode: .default)
    updateTimer?.fire()
}

Critical: Add cleanup code in viewDidDisappear to invalidate the Timer and break the cycle:

override func viewDidDisappear(_ animated: Bool) {
    super.viewDidDisappear(animated)
    updateTimer?.invalidate()
    updateTimer = nil
}

Quick Notes

  • Your @objc private func updateOnlineTrack() is correctly declared—no issues there since the compiler accepts it.
  • Always call the super implementation of lifecycle methods like viewDidAppear and viewDidDisappear—omitting this can cause unexpected behavior.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:24:46