我想停止这个计时器,然后从我停止的地方重新启动它。
secondsTimer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(addSeconds), userInfo: nil, repeats: true)
下面,有人建议我不应该在我的计时器处理程序中增加一个计时器。为什么不?
例如,使用GCD计时器:
func countSeconds() {
secondsTimer = DispatchSource.makeTimerSource(queue: .main)
secondsTimer?.schedule(deadline: .now(), repeating: 1.0)
secondsTimer?.setEventHandler { [weak self] in
self?.addSeconds()
}
}
@objc func addSeconds() {
seconds += 1
}
func startGame() {
secondsTimer?.resume()
}
答案 0 :(得分:2)
我们不会暂停/恢复Timer
个实例。我们用invalidate()
阻止它们。当你想重新启动时,只需创建新的计时器。
请参阅Xcode中提供的the Timer
documentation。
请注意,您可以suspend
和resume
GCD计时器DispatchSourceTimer
。
var timer: DispatchSourceTimer? // note, unlike `Timer`, we have to maintain strong reference to GCD timer sources
func createTimer() {
timer = DispatchSource.makeTimerSource(queue: .main)
timer?.schedule(deadline: .now(), repeating: 1.0)
timer?.setEventHandler { [weak self] in // assuming you're referencing `self` in here, use `weak` to avoid strong reference cycles
// do something
}
// note, timer is not yet started; you have to call `timer?.resume()`
}
func startTimer() {
timer?.resume()
}
func pauseTiemr() {
timer?.suspend()
}
func stopTimer() {
timer?.cancel()
timer = nil
}
请注意,如果您希望suspend
和resume
使用GCD DispatchSourceTimer
,我建议您不要这样做。根据需要调用invalidate
并重新创建Timer
非常简单,所以就这样做。为了完整起见,我只提供此GCD信息。
顺便说一句,作为一般原则,永远不会增加"计时器处理程序中的一些计数器这是一个常见的菜鸟错误。定时器无法保证每次或准确精确地发射。始终在开始时保存一些参考时间,然后在事件处理程序中计算当前时间和开始时间之间的差异。例如,扩展我的GCD计时器示例:
func createTimer() {
timer = DispatchSource.makeTimerSource(queue: .main)
timer?.schedule(deadline: .now(), repeating: 0.1)
let formatter = DateComponentsFormatter()
formatter.unitsStyle = .positional
formatter.allowedUnits = [.hour, .minute, .second, .nanosecond]
formatter.zeroFormattingBehavior = .pad
timer?.setEventHandler { [weak self] in
guard let start = self?.start else { return }
let elapsed = (self?.totalElapsed ?? 0) + CACurrentMediaTime() - start
self?.label.text = formatter.string(from: elapsed)
}
}
var start: CFTimeInterval? // if nil, timer not running
var totalElapsed: CFTimeInterval?
@objc func didTapButton(_ button: UIButton) {
if start == nil {
startTimer()
} else {
pauseTimer()
}
}
private func startTimer() {
start = CACurrentMediaTime()
timer?.resume()
}
private func pauseTimer() {
timer?.suspend()
totalElapsed = (totalElapsed ?? 0) + (CACurrentMediaTime() - start!)
start = nil
}
答案 1 :(得分:0)
您可以在swift4中启动,停止和重置计时器
class ViewController: UIViewController {
var counter = 0
var timer = Timer()
var totalSecond = 20
@IBOutlet weak var label1: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
@IBAction func start_btn(_ sender: Any) {
timer.invalidate() // just in case this button is tapped multiple times
timer = Timer.scheduledTimer(timeInterval: 0.5, target: self, selector: #selector(timerAction), userInfo: nil, repeats: true)
}
@IBAction func stop_btn(_ sender: Any) {
do {
self.timer.invalidate()
}
func timeFormatted(_ totalSeconds: Int) -> String {
let seconds: Int = totalSeconds % 60
return String(format: "0:%02d", seconds)
}
}
@IBAction func reset_btn(_ sender: Any) {
timer.invalidate()
//timerAction()
counter = 0
label1.text = "\(counter)"
}
@objc func timerAction()
{
counter += 1
label1.text = "\(counter)"
}
}
答案 2 :(得分:0)
我用这个代码来做:
var timer: Timer?
func startTimer() {
timer = .scheduledTimer(withTimeInterval: 4, repeats: false, block: { _ in
// Do whatever
})
}
func resetTimer() {
timer?.invalidate()
startTimer()
}
答案 3 :(得分:-1)
您可以将Timer声明为“弱变量”,而不是像这样的“ var”:
weak var timer: Timer?
现在,您可以通过以下方式暂停计时器:
timer?.invalidate()
要恢复:
timer?.fire()