【问题标题】:How can I pause and resume NSTimer.scheduledTimerWithTimeInterval in swift?如何快速暂停和恢复 NSTimer.scheduledTimerWithTimeInterval?
【发布时间】:2015-06-07 00:18:33
【问题描述】:

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

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?请帮帮我。

【问题讨论】:

  • 澄清一下,您想在按下“暂停”按钮时暂停现有计时器......并且您想在按下“恢复”按钮时恢复计时器...... ..正确的?

标签: swift ios8 nstimer


【解决方案1】:

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

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
    }
}

【讨论】:

  • @PanduArifSeptian 如果您正在寻找适用于 Swift 2 的功能,这应该是公认的答案。它适用于我。
【解决方案2】:

开始

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

暂停

timer.invalidate()

重置

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

'label' 是输出的计时器。

【讨论】:

    【解决方案3】:

    开始:

    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" 这样的东西。只需使用“启动计时器的相同代码”在暂停后恢复它。

    【讨论】:

      【解决方案4】:

      阻止它

        time3.invalidate() 
      

      重新开始

        time3.fire()
      

      【讨论】:

      • @Christos Hadjikyriacou 当我放火时,什么也没有发生。有什么帮助吗?
      • 我认为你应该重新初始化 NSTimer。
      • 来自 Apple 文档:“(无效)阻止接收器再次触发并请求将其从运行循环中删除。”一旦调用 invalidate,您应该将计时器设置为 nil 并(重新)实例化/再次触发以“重新启动”。
      • .fire() 不会再次启动计时器(从某种意义上说,它将继续重复对选择器的调用。)为了做到这一点(这就是 OP 所说的“恢复” ) 你必须重新初始化计时器。
      【解决方案5】:

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

      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)
          }
      }
      

      【讨论】:

        【解决方案6】:

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

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

        停止计时器再次触发并请求将其从 它的运行循环。


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

        我们可以通过以下方式暂停计时器,方法是保存计时器的剩余秒数,直到它再次触发。

        //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。

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

        【讨论】:

          【解决方案7】:

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

          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

          【讨论】:

            【解决方案8】:

            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
                  }          
             }
            

            【讨论】:

              【解决方案9】:

              暂停计时器:timer.invalidate()

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

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

              【讨论】:

                猜你喜欢
                • 2014-11-20
                • 1970-01-01
                • 2019-06-28
                • 2020-06-14
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2013-03-04
                相关资源
                最近更新 更多