我正在尝试制作连接到按钮的倒数计时器,并且目前正在使用
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(ViewController.clock), userInfo: nil, repeats: true)
但是,我想要这样,如果我按下相同的按钮,则新计时器将以类似的设置启动,因此在控制台中,有2个,3个等同时倒数计时器。 每当我按下按钮时,如何使新计时器生成与上一个相同的设置,但旧计时器仍处于活动状态并滴答下来?
答案 0 :(得分:4)
要跟踪各种计时器,您想创建一个计时器数组([Timer]
),并创建一个TimerState
作为userInfo
对象传递到每个计时器中。然后,在调用updateTimer()
时,您可以以state
的身份访问该计时器的timer.userInfo
并使用它。当计时器到达0
时,请呼叫invalidate()
并将其从计时器列表中删除。
如果用户按下停止所有计时器按钮,则使用timers
数组停止所有活动计时器。
import UIKit
class TimerState {
let number: Int
var count: Int
init(number: Int, count: Int) {
self.number = number
self.count = count
}
}
class ViewController: UIViewController {
var timerNumber = 1
var startingCount = 10
// Array to hold active timers so that all can be stopped
var timers = [Timer]()
@IBAction func startTimer(_ sender: UIButton) {
let state = TimerState(number: timerNumber, count: startingCount)
let timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(updateTimer), userInfo: state, repeats: true)
timers.append(timer)
timerNumber += 1
}
@objc func updateTimer(_ timer: Timer) {
guard let state = timer.userInfo as? TimerState else { return }
state.count -= 1
if state.count == 0 {
print("Timer \(state.number) is done")
timer.invalidate()
// remove this timer from the list of active timers
if let index = timers.firstIndex(of: timer) {
timers.remove(at: index)
}
} else {
print("Timer \(state.number): \(state.count)")
}
}
@IBAction func stopAllTimers(_ sender: UIButton) {
for timer in timers {
guard let state = timer.userInfo as? TimerState else { continue }
print("Timer \(state.number) stopped")
timer.invalidate()
}
}
}
按 Start Timer 按钮3次将在控制台中产生以下输出:
Timer 1: 9 Timer 1: 8 Timer 1: 7 Timer 2: 9 Timer 1: 6 Timer 2: 8 Timer 1: 5 Timer 2: 7 Timer 3: 9 Timer 1: 4 Timer 2: 6 Timer 3: 8 Timer 1: 3 Timer 2: 5 Timer 3: 7 Timer 1: 2 Timer 2: 4 Timer 3: 6 Timer 1: 1 Timer 2: 3 Timer 3: 5 Timer 1 is done Timer 2: 2 Timer 3: 4 Timer 2: 1 Timer 3: 3 Timer 2 is done Timer 3: 2 Timer 3: 1 Timer 3 is done
答案 1 :(得分:1)
根据您的代码:
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(ViewController.clock), userInfo: nil, repeats: true)
我假设您在timer
中将ViewController
声明为实例变量,例如:
class ViewController: UIViewController {
var timer: Timer?
@IBAction func tapped(_ sender: Any) {
timer?.invalidate()
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(ViewController.clock), userInfo: nil, repeats: true)
}
@objc func clock() {
print("counting...")
}
}
因此,即使您使用的是相同的Timer
实例,每次单击按钮都将安排新的计时会话。在这种情况下,您应该做的是每次 invalidate timer
,然后再为其分配Timer.scheduledTimer
:
阻止计时器再次触发并请求将其从中移除 它的运行循环。
在按钮操作方法中,首先添加timer?.invalidate()
:
@IBAction func tapped(_ sender: Any) {
timer?.invalidate()
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(ViewController.clock), userInfo: nil, repeats: true)
}
答案 2 :(得分:0)
为每次按下按钮(如果确实需要多个计时器)创建一个具有相同属性的新Timer()
实例。
尽管值得保留所有计时器的列表,以便您在不再需要它们时可以使用它们(因此,如果有人向该按钮发送了垃圾邮件,则不会建立许多计时器)。
答案 3 :(得分:0)
好吧,这取决于您是否需要跟踪所有这些计时器。如果不是很简单。每次单击按钮时,只需创建一个计时器即可:
func buttonDidClick() {
Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(ViewController.clock), userInfo: nil, repeats: true)
}
如果您需要跟踪这些计时器,请使用数组:
func buttonDidClick() {
myArray.append(Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(ViewController.clock), userInfo: nil, repeats: true))
}
这样,您甚至可以取消所有计时器或执行所需的任何操作。