如何在 swift 中暂停和恢复 NSTimer.scheduledTimerWithTimeInterval?

How can I pause and resume NSTimer.scheduledTimerWithTimeInterval in swift?

我正在开发一款游戏,我想创建一个暂停菜单。这是我的代码:

self.view?.paused = true

但是NSTimer.scheduledTimerWithTimeInterval仍然运行宁...

 for var i=0; i < rocketCount; i++ {
    var a: NSTimeInterval = 1
    ii += a
    delaysShow = 2.0 + ((stimulus + interStimulus) * ii)       
    var time3 = NSTimer.scheduledTimerWithTimeInterval(delaysShow!, target: self, selector: Selector("showRocket:"), userInfo: rocketid[i], repeats: false)
 }

我希望 time3 在玩家点击暂停菜单时暂停计时器,并在玩家返回游戏时继续 运行 计时器,但如何才能暂停 NSTimer.scheduledTimerWithTimeInterval?请帮助我。

阻止它

  time3.invalidate() 

重新开始

  time3.fire()

您需要使它失效并重新创建它。然后,如果您有相同的按钮来暂停和恢复计时器,则可以使用 isPaused 布尔值来跟踪状态:

var isPaused = true
var timer = NSTimer()    
@IBAction func pauseResume(sender: AnyObject) {     
    if isPaused{
        timer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: Selector("somAction"), userInfo: nil, repeats: true)
        isPaused = false
    } else {
        timer.invalidate()
        isPaused = true
    }
}

开始:

timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: Selector("updateView"), userInfo: nil, repeats: true)

要恢复:

timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: Selector("updateView"), userInfo: nil, repeats: true)

暂停:

timer.invalidate

这对我有用。诀窍是不要寻找 "timer.resume""timer.validate" 之类的东西。暂停后使用"the same code for starting a timer"恢复即可。

您无法恢复倒计时。 而不是恢复 - 只需创建一个新计时器。

class SomeClass : NSObject { // class must be NSObject, if there is no "NSObject" you'll get the error at runtime

    var timer = NSTimer()

    init() {
        super.init()
        startOrResumeTimer()
    }

    func timerAction() {
        NSLog("timer action")
    }

    func pauseTimer() {
        timer.invalidate
    }

    func startOrResumeTimer() {
        timer = NSTimer.scheduledTimerWithTimeInterval(0.5, target: self, selector: Selector("timerAction"), userInfo: nil, repeats: true)
    }
}

开始

timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(ViewController.action), userInfo: nil, repeats: true)

暂停

timer.invalidate()

重置

time += 1
label.text = String(time)

'label'是输出的定时器。

SWIFT3

全球宣言:

 var swiftTimer = Timer()
 var count = 30
 var timer = Timer()
 @IBOutlet weak var CountDownTimer: UILabel!

viewDidLoad

override func viewDidLoad() { super.viewDidLoad() BtnStart.tag = 0 }

触发的 IBACTION:

@IBAction func BtnStartTapped(_ sender: Any) {
      if BtnStart.tag == 0 {
           BtnStart.setTitle("STOP", for: .normal)
           timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(ScoreBoardVC.update), userInfo: nil, repeats: true)

           BtnStart.tag = 1
      } else {

           BtnStart.setTitle("START", for: .normal)
           timer.invalidate()

           BtnStart.tag = 0
      }                    
 }

处理事物的函数:

func update(){

      if(count > 0){
           let minutes = String(count / 60)
           let ConvMin = Float(minutes)
           let minuttes1 = String(format: "%.0f", ConvMin!)

           print(minutes)
           let seconds = String(count % 60)
           let ConvSec = Float(seconds)
           let seconds1 = String(format: "%.0f", ConvSec!)

           CountDownTimer.text = (minuttes1 + ":" + seconds1)
           count += 1
      }          
 }

暂停计时器:timer.invalidate()

恢复计时器:重新创建计时器。它工作正常。

timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(mainController.updateTimer), userInfo: nil, repeats: true)

尽管这里公开的解决方案很好,但我认为缺少一个重要的见解。就像这里的很多人解释的那样,计时器无效()并重新创建是最好的选择。但有人可能会争辩说你可以这样做:

var paused:Bool

func timerAction() {
    if !paused {
        // Do stuff here
    }
}

更容易实现,但效率会降低。

出于能源影响的原因,Apple 提倡尽可能避免使用计时器并更喜欢事件通知。如果您确实需要使用计时器,您应该通过使当前的计时器无效来有效地实现暂停定时器。在此处阅读 Apple 能源效率指南中有关计时器的建议: https://developer.apple.com/library/content/documentation/Performance/Conceptual/EnergyGuide-iOS/MinimizeTimerUse.html

我刚刚在我的游戏中解决了类似的问题,并找到了一个简单的解决方案。

首先我应该像其他人一样指出,Timer 和 NSTimer 没有暂停功能。您必须使用 Timer.invalidate() 停止计时器。使 Timer 失效后,必须再次初始化才能启动 Timer。引用 https://developer.apple.com/documentation/foundation/timer,函数 .invalidate() -

Stops the timer from ever firing again and requests its removal from its run loop.


要暂停计时器,我们可以使用 Timer.fireDate,这是计时器(和 NSTimer)保存计时器将来触发日期的地方。

以下是我们可以通过保存计时器在再次触发之前剩余的秒数来暂停计时器的方法。

//The variable we will store the remaining timers time in
var timeUntilFire = TimeInterval()

//The timer to pause
var gameTimer = Timer.scheduledTimer(timeInterval: delaysShow!, target: self, selector: #selector(GameClass.showRocket), userInfo: rocketid[i], repeats: false)

func pauseTimer()
{
    //Get the difference in seconds between now and the future fire date
    timeUntilFire = gameTimer.fireDate.timeIntervalSinceNow
    //Stop the timer
    gameTimer.invalidate()
}

func resumeTimer()
{
    //Start the timer again with the previously invalidated timers time left with timeUntilFire
    gameTimer = Timer.scheduledTimer(timeInterval: timeUntilFire, target: self, selector: #selector(GameClass.showRocket), userInfo: rocketid[i], repeats: false)
}

注意:在获取 fireDate 之前不要使 Timer 无效。在调用 invalidate() 之后,Timer 似乎将 fireDate 重置为 2001-01-01 00:00:00 +0000.

第二个注意: 计时器可能会在其设置的触发日期后触发。这将导致一个负数,这将使 Timer 在 0.1 毫秒后默认为 运行。 https://developer.apple.com/documentation/foundation/timer/1412416-scheduledtimer