【问题标题】:How can I make a countdown with NSTimer?如何使用 NSTimer 进行倒计时?
【发布时间】:2015-06-05 03:23:48
【问题描述】:

如何使用 Swift 使用 NSTimer 进行倒计时?

【问题讨论】:

    标签: xcode swift nstimer


    【解决方案1】:

    这是一个鸡蛋计时器。

    import UIKit
    
    class ViewController: UIViewController {
        let eggTimes = ["Soft": 0.1, "Medium": 2, "Hard": 3]
        
        var eggTime = 0
        
        var timer = Timer()
        
        @IBOutlet weak var label: UILabel!
        
        @IBAction func b(_ sender: UIButton) {
        
        timer.invalidate()
        
        let hardness = sender.currentTitle!
        eggTime = Int(eggTimes[hardness]! * 60)
        timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(update), userInfo: nil, repeats: true)
            }
        @objc func update() {
            if (eggTime > 0) {
                print("\(eggTime) seconds")
                eggTime -= 1
                }
            if (eggTime == 0){
                label.text = ("done")
            }
        }
    }
    

    【讨论】:

      【解决方案2】:

      你真的不应该。 Grand Central Dispatch 更可靠。

      【讨论】:

        【解决方案3】:
        import UIKit
        
        class ViewController: UIViewController {
        
            let eggTimes = ["Soft": 300, "Medium": 420, "Hard": 720]
            
            var secondsRemaining = 60
        
            @IBAction func hardnessSelected(_ sender: UIButton) {
                let hardness = sender.currentTitle!
        
                secondsRemaining = eggTimes[hardness]!
        
                Timer.scheduledTimer(timeInterval: 1.0, target: self, selector:
                    #selector(UIMenuController.update), userInfo: nil, repeats: true)
            }
            @objc func countDown() {
                 if secondsRemaining > 0 {
                     print("\(secondsRemaining) seconds.")
                    secondsRemaining -= 1
                
                 }
            }
        }
        

        【讨论】:

        • 欢迎来到 Stack Overflow。在回答具有已接受答案的旧问题(寻找绿色 ✓)以及其他答案时,请确保您的答案添加了新内容或对它们有帮助。 (您回答的原因是什么?其他答案是否不够,错误,过时,......?)虽然此代码 sn-p 可能会解决问题,但它没有解释为什么或如何回答问题。请考虑include an explanation for your code,因为这有助于提高您的帖子质量。
        • 从这里开始,请通过tour 了解 Stack Overflow 的工作原理,并查看contribution guideline
        【解决方案4】:

        Swift 4.1 和 Swift 5。 updatetime 方法将在每秒后调用一次,秒数将显示在 UIlabel 上。

             var timer: Timer?
             var totalTime = 60
            
             private func startOtpTimer() {
                    self.totalTime = 60
                    self.timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(updateTimer), userInfo: nil, repeats: true)
                }
            
            @objc func updateTimer() {
                    print(self.totalTime)
                    self.lblTimer.text = self.timeFormatted(self.totalTime) // will show timer
                    if totalTime != 0 {
                        totalTime -= 1  // decrease counter timer
                    } else {
                        if let timer = self.timer { 
                            timer.invalidate()
                            self.timer = nil
                        }
                    }
                }
            func timeFormatted(_ totalSeconds: Int) -> String {
                let seconds: Int = totalSeconds % 60
                let minutes: Int = (totalSeconds / 60) % 60
                return String(format: "%02d:%02d", minutes, seconds)
            }
        

        【讨论】:

        • 每当我们添加 self.timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(updateTimer), userInfo: nil, repeats: true) 这里,timeInterval = 1.0 所以基本上要显示计时器值,它需要 1 秒以避免这种情况,比如计时器应该在火灾时立即运行,我应该做些什么解决方法?尝试使 timeInterval = 0.1 但这不是一个好主意,因为计时器函数将每 0.1 秒调用一次。
        【解决方案5】:

        带有闭包的 Swift 5:

        class ViewController: UIViewController {
            
        var secondsRemaining = 30
            
        @IBAction func startTimer(_ sender: UIButton) {
                
            Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { (Timer) in
                if self.secondsRemaining > 0 {
                    print ("\(self.secondsRemaining) seconds")
                    self.secondsRemaining -= 1
                } else {
                    Timer.invalidate()
                }
            }
                    
        }
        

        【讨论】:

        • 如何使计时器失效?
        • 我建议将 self.invalidate() 替换为 Timer.invalidate() 因为使用 self 会显示未解析的标识符
        • 从我在这里看到的情况来看,这将导致一个保留周期(我有 95% 的把握——没有进行任何测试)。您需要弱捕获 self 以从计时器闭包中引用它。您还将名称 Timer 与大写 T 组合起来,使其看起来像一个类型,因此 Timer.invalidate() 读取为静态函数。这应该像{ [weak self] (timer) in 那样进行更改,以捕获弱自我并明确timer 是计时器的实例。
        【解决方案6】:

        供新手在 Playground 中使用,在 Swift 5、Xcode 11 中使用:

        Import UIKit
        
        var secondsRemaining = 10
            
        Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { (Timer) in
            if secondsRemaining > 0 {
                print ("\(secondsRemaining) seconds")
                secondsRemaining -= 1
            } else {
                Timer.invalidate()
            }
        }
        

        【讨论】:

        • 最初的问题是关于 NSTimer;在您的答案中解释两者之间的关系会有所帮助。
        • 嗨@shader NSTimer 类现在改为Timer,也许我应该澄清一下
        【解决方案7】:

        将此添加到代码的末尾... 并使用您要倒计时到的参数调用 startTimer 函数... 例如(距离现在日期的未来 2 小时)-> startTimer(for: Date().addingTimeInterval(60*60*2))

        Click here to view a screenshot of iPhone Simulator of how it'll look

        extension ViewController
        {
            func startTimer(for theDate: String)
            {
                let todaysDate = Date()
                let tripDate = Helper.getTripDate(forDate: theDate)
                let diffComponents = Calendar.current.dateComponents([.hour, .minute], from: Date(), to: tripDate)
                if let hours = diffComponents.hour
                {
                    hoursLeft = hours
                }
                if let minutes = diffComponents.minute
                {
                    minutesLeft = minutes
                }
                if tripDate > todaysDate
                {
                    timer = Timer.scheduledTimer(timeInterval: 1.00, target: self, selector: #selector(onTimerFires), userInfo: nil, repeats: true)
                }
                else
                {
                    timerLabel.text = "00:00:00"
                }
            }
            
            @objc func onTimerFires()
            {
                secondsLeft -= 1
                
                //timerLabel.text = "\(hoursLeft):\(minutesLeft):\(secondsLeft)"
                timerLabel.text = String(format: "%02d:%02d:%02d", hoursLeft, minutesLeft, secondsLeft)
                if secondsLeft <= 0 {
                    if minutesLeft != 0
                    {
                        secondsLeft = 59
                        minutesLeft -= 1
                    }
                }
                
                if minutesLeft <= 0 {
                    if hoursLeft != 0
                    {
                        minutesLeft = 59
                        hoursLeft -= 1
                    }
                }
                
                if(hoursLeft == 0 && minutesLeft == 0 && secondsLeft == 0)
                {
                    timer.invalidate()
                }
                
            }
        }
        

        【讨论】:

          【解决方案8】:

          Swift 5 的另一种方式。 难以与 UI 交互

          我想展示一个在倒计时期间防止用户与其他 UI 元素交互的解决方案。 在 cmets 中,我解释了每一行代码的含义。

           var timeToSet = 0
           var timer: Timer?
          
           ...
          
           @IBAction func btnWasPressed(_ sender: UIButton) {
          
                //Setting the countdown time
                timeLeft = timeToSet
                //Disabling any previous timers.
                timer?.invalidate()
                //Initialization of the Timer with interval every 1 second with the function call.
                timer = Timer(timeInterval: 1.0, target: self, selector: #selector(countDown), userInfo: nil, repeats: true)
                //Adding Timer to the current loop
                RunLoop.current.add(timer!, forMode: .common)
          
            }
          
           ...
          
           @objc func countDown() {
          
               if timeLeft > 0 {
                   print(timeLeft)
                   timeLeft -= 1
               } else {
                   // Timer stopping
                   timer?.invalidate()
               }
           }
          

          【讨论】:

            【解决方案9】:

            问题一:

            @IBOutlet var countDownLabel: UILabel!
            
            var count = 10
            
            override func viewDidLoad() {
                super.viewDidLoad()
            
                var timer = Timer.scheduledTimer(timeInterval: 0.4, target: self, selector: #selector(UIMenuController.update), userInfo: nil, repeats: true)
            }
            
            func update() {
                if(count > 0) {
                    countDownLabel.text = String(count--)
                }
            }
            

            问题 2:

            两者都可以。 SpriteKit 是您用于场景、运动等的 SDK。Simple View Application 是项目模板。他们不应该冲突

            【讨论】:

            • 考虑使用 count-=1 而不是 C 中的 -- 运算符。我会把 String(count) 放在下面,count-=1。
            【解决方案10】:

            这适用于现在的 swift 5.0 和新闻

            var secondsRemaining = 60
            
            
            Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(updateCounter), userInfo: nil, repeats: true)
            }
            @objc func updateCounter(){
                if secondsRemaining > 0 {
                print("\(secondsRemaining) seconds.")
                secondsRemaining -= 1
                        }
                    }
            

            【讨论】:

              【解决方案11】:

              在 Swift 5.1 中这将起作用:

              var counter = 30
              
              override func viewDidLoad() {
                  super.viewDidLoad()
              
                  Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(updateCounter), userInfo: nil, repeats: true)
              }
              
              
              
              @objc func updateCounter() {
                  //example functionality
                  if counter > 0 {
                      print("\(counter) seconds to the end of the world")
                      counter -= 1
                  }
              }
              

              【讨论】:

              • 太棒了!为我工作:) 我只是添加了计时器失效以避免在多次调用计时器时出现问题。
              • 我想要同样的东西,定时器应该被调用几次。你是怎么创造的?可以分享一下吗
              【解决方案12】:

              Swift4

                  @IBOutlet weak var actionButton: UIButton!
                  @IBOutlet weak var timeLabel: UILabel!
                  var timer:Timer?
                  var timeLeft = 60
              
              override func viewDidLoad() {
                  super.viewDidLoad()
                  setupTimer()
              }
              
              func setupTimer() {
                  timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(onTimerFires), userInfo: nil, repeats: true)
              }
              
              @objc func onTimerFires() {
                  timeLeft -= 1
                  timeLabel.text = "\(timeLeft) seconds left"
              
                  if timeLeft <= 0 {
                      actionButton.isEnabled = true
                      actionButton.setTitle("enabled", for: .normal)
                      timer?.invalidate()
                      timer = nil
                  }
              }
              
              @IBAction func btnClicked(_ sender: UIButton) {
                  print("API Fired")
              }
              

              【讨论】:

                【解决方案13】:

                XCode 10 与 Swift 4.2

                import UIKit
                
                class ViewController: UIViewController {
                
                   var timer = Timer()
                   var totalSecond = 10
                
                   override func viewDidLoad() {
                       super.viewDidLoad()
                       startTimer()
                   }
                
                
                   func startTimer() {
                       timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(updateTime), userInfo: nil, repeats: true)
                   }
                
                   @objc func updateTime() {
                
                        print(timeFormatted(totalSecond))
                
                        if totalSecond != 0 {
                           totalSecond -= 1
                        } else {
                           endTimer()
                        }
                    }
                
                    func endTimer() {
                        timer.invalidate()
                    }
                
                    func timeFormatted(_ totalSeconds: Int) -> String {
                        let seconds: Int = totalSeconds % 60
                        return String(format: "0:%02d", seconds)
                    }
                
                }
                

                【讨论】:

                  【解决方案14】:

                  斯威夫特 4

                  Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(self.updateTime), userInfo: nil, repeats: true)
                  

                  更新功能

                  @objc func updateTime(){
                      debugPrint("jalan")
                  }
                  

                  【讨论】:

                    【解决方案15】:

                    斯威夫特 3

                    private let NUMBER_COUNT_DOWN   = 3
                    
                    var countDownLabel = UILabel()
                    var countDown = NUMBER_COUNT_DOWN
                    var timer:Timer?
                    
                    
                    private func countDown(time: Double)
                    {
                        countDownLabel.frame = CGRect(x: 0, y: 0, width: 300, height: 300)
                        countDownLabel.font = UIFont.systemFont(ofSize: 300)
                        countDownLabel.textColor = .black
                        countDownLabel.center = CGPoint(x: self.view.frame.width / 2, y: self.view.frame.height / 2)
                    
                        countDownLabel.textAlignment = .center
                        self.view.addSubview(countDownLabel)
                        view.bringSubview(toFront: countDownLabel)
                    
                        timer = Timer.scheduledTimer(timeInterval: time, target: self, selector: #selector(updateCountDown), userInfo: nil, repeats: true)
                    }
                    
                    func updateCountDown() {
                        if(countDown > 0) {
                            countDownLabel.text = String(countDown)
                            countDown = countDown - 1
                        } else {
                            removeCountDownLable()
                        }
                    }
                    
                    private func removeCountDownLable() {
                        countDown = NUMBER_COUNT_DOWN
                        countDownLabel.text = ""
                        countDownLabel.removeFromSuperview()
                    
                        timer?.invalidate()
                        timer = nil
                    }
                    

                    【讨论】:

                      【解决方案16】:

                      制作倒计时应用 Xcode 8.1、Swift 3

                      import UIKit
                      import Foundation
                      
                      class ViewController: UIViewController, UITextFieldDelegate {
                      
                          var timerCount = 0
                          var timerRunning = false
                      
                          @IBOutlet weak var timerLabel: UILabel! //ADD Label
                          @IBOutlet weak var textField: UITextField! //Add TextField /Enter any number to Countdown
                      
                          override func viewDidLoad() {
                              super.viewDidLoad()
                      
                              //Reset
                              timerLabel.text = ""
                              if timerCount == 0 {
                                  timerRunning = false
                              }
                      }
                      
                             //Figure out Count method
                          func Counting() {
                              if timerCount > 0 {
                              timerLabel.text = "\(timerCount)"
                                  timerCount -= 1
                              } else {
                                  timerLabel.text = "GO!"
                      
                              }
                      
                          }
                      
                          //ADD Action Button
                          @IBAction func startButton(sender: UIButton) {
                      
                              //Figure out timer
                              if timerRunning == false {
                               _ = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(ViewController.Counting), userInfo: nil, repeats: true)
                                  timerRunning = true
                              }
                      
                              //unwrap textField and Display result
                              if let countebleNumber = Int(textField.text!) {
                                  timerCount = countebleNumber
                                  textField.text = "" //Clean Up TextField
                              } else {
                                  timerCount = 3 //Defoult Number to Countdown if TextField is nil
                                  textField.text = "" //Clean Up TextField
                              }
                      
                          }
                      
                          //Dismiss keyboard
                          func keyboardDismiss() {
                              textField.resignFirstResponder()
                          }
                      
                          //ADD Gesture Recignizer to Dismiss keyboard then view tapped
                          @IBAction func viewTapped(_ sender: AnyObject) {
                              keyboardDismiss()
                          }
                      
                          //Dismiss keyboard using Return Key (Done) Button
                          func textFieldShouldReturn(_ textField: UITextField) -> Bool {
                              keyboardDismiss()
                      
                              return true
                          }
                      
                      }
                      

                      https://github.com/nikae/CountDown-

                      【讨论】:

                        【解决方案17】:

                        定时器的变量

                        var timer = 60
                        

                        以 1.0 为间隔的 NSTimer

                        var clock = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: "countdown", userInfo: nil, repeats: true)
                        

                        在这里你可以减少计时器

                        func countdown() {
                            timer--
                        }
                        

                        【讨论】:

                        • 应该是 Selector("countdown")
                        • 在范围内找不到运算符'--';你的意思是'-= 1'吗?我们不应该使用“timer--”,而是使用“counter -= 1”
                        猜你喜欢
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 2013-06-25
                        • 1970-01-01
                        • 1970-01-01
                        相关资源
                        最近更新 更多