Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/98.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 快速创建独立计时器_Ios_Swift_Swift4_Nstimer - Fatal编程技术网

Ios 快速创建独立计时器

Ios 快速创建独立计时器,ios,swift,swift4,nstimer,Ios,Swift,Swift4,Nstimer,我正在尝试制作一个连接到按钮的倒计时计时器,目前正在使用 timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(ViewController.clock), userInfo: nil, repeats: true) 然而,我想要它,所以如果我按下相同的按钮,一个新的计时器将以类似的设置启动,因此在控制台中有2个、3个等。同时运行倒计时计时器。 如何使每当我按下按钮时,新计时器生成的设置与

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

timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(ViewController.clock), userInfo: nil, repeats: true)
然而,我想要它,所以如果我按下相同的按钮,一个新的计时器将以类似的设置启动,因此在控制台中有2个、3个等。同时运行倒计时计时器。 如何使每当我按下按钮时,新计时器生成的设置与前一个相同,但旧计时器仍处于活动状态并在滴答作响?

为每个按钮按下创建一个具有相同属性的新
计时器()
实例(如果确实需要多个计时器)


保留一份所有计时器的列表是值得的,这样你就可以在不再需要它们时处理它们(这样,如果有人滥发了按钮,你就不会有几十个计时器了)。

好吧,这取决于你是否需要跟踪所有这些计时器。如果不是,那就相当简单了。每次单击按钮时,只需创建一个计时器:

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))
    }
这样,您甚至可以取消所有计时器或执行任何需要的操作。

基于您的代码:

timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(ViewController.clock), userInfo: nil, repeats: true)
我假设您在
ViewController
中将
timer
声明为实例变量,类似于:

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.scheduledTimer
之前,每次执行
timer

停止计时器再次启动,并请求将其从 它的运行循环

在按钮操作方法中,首先添加
timer?.invalidate()

@IBAction func tapped(_ sender: Any) {
    timer?.invalidate()

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

要跟踪各种计时器,您需要创建一个计时器数组(
[Timer]
),并创建一个
TimerState
作为
userInfo
对象传递到每个计时器中。然后,当调用
updateTimer()
时,您可以将该计时器的
状态作为
timer.userInfo
访问并使用它。当计时器达到
0
时,调用
invalidate()
,并将其从计时器列表中删除

如果用户按下停止所有计时器按钮,则使用
计时器
阵列停止所有活动计时器


按下启动计时器按钮3次可在控制台中产生以下输出:


如果您对现有的
计时器
实例执行操作,您只需覆盖它(因此,您为什么看不到“旧的”实例)。是否希望为每个按钮按下生成一个新的运行循环?如果是,那么这应该是您代码的默认行为…假设我将两个计时器都附加到数组中,那么我如何从这两个同时滴答作响的计时器中打印数据?您可以在数组中循环,使用timer.invalidate()停止所有计时器,并使用timer.scheduledTimer再次实例化它们(用户每次单击按钮时都应执行此操作)。
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()
        }
    }
}
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