如何使用 NSTimer 进行倒计时?
Posted
技术标签:
【中文标题】如何使用 NSTimer 进行倒计时?【英文标题】:How can I make a countdown with NSTimer? 【发布时间】:2015-06-05 03:23:48 【问题描述】:如何使用 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”以上是关于如何使用 NSTimer 进行倒计时?的主要内容,如果未能解决你的问题,请参考以下文章