快速创建单独的计时器

时间:2018-12-19 15:12:51

标签: ios swift swift4 nstimer

我正在尝试制作连接到按钮的倒数计时器,并且目前正在使用

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

但是,我想要这样,如果我按下相同的按钮,则新计时器将以类似的设置启动,因此在控制台中,有2个,3个等同时倒数计时器。 每当我按下按钮时,如何使新计时器生成与上一个相同的设置,但旧计时器仍处于活动状态并滴答下来?

4 个答案:

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

这样,您甚至可以取消所有计时器或执行所需的任何操作。