Быстрое создание отдельных таймеров - PullRequest
0 голосов
/ 19 декабря 2018

Я пытаюсь сделать таймер обратного отсчета, который подключается к кнопке, и в настоящее время использую

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

Однако я хочу, чтобы, если я нажимаю ту же кнопку, новый таймер запускается с аналогичнымнастройки, поэтому в консоли одновременно работают 2, 3 и т. д. таймеры обратного отсчета.Как сделать так, чтобы каждый раз, когда я нажимал кнопку, генерировался новый таймер с теми же настройками, что и предыдущий, но старый все еще активен и отключается?

Ответы [ 4 ]

0 голосов
/ 19 декабря 2018

Чтобы отслеживать различные таймеры, вы хотите создать массив таймеров ([Timer]) и создать TimerState для передачи в каждый таймер как объект userInfo.Затем, когда вызывается updateTimer(), вы можете получить доступ к state для этого таймера как timer.userInfo и использовать его.Когда таймер достигает значения 0, вызовите invalidate() и удалите его из списка таймеров.

Использует массив timers для остановки всех активных таймеров, если пользователь нажимает Stop AllКнопка таймеров .

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
0 голосов
/ 19 декабря 2018

Ну, это зависит от того, нужно ли вам отслеживать все эти таймеры или нет.Если нет, это довольно просто.Просто создайте таймер каждый раз, когда вы нажимаете кнопку:

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

Таким образом, вы можете даже отменить всетаймеры или делать все, что вам нужно.

0 голосов
/ 19 декабря 2018

Исходя из вашего кода:

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.В этом случае вы должны аннулировать 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)
}
0 голосов
/ 19 декабря 2018

Создайте новый экземпляр Timer() для каждого нажатия кнопки (если вы действительно хотите использовать несколько таймеров) с одинаковыми свойствами.

Хотя стоило бы сохранить список всех ваших таймеров, чтобы вы могли иметь делос ними, когда они вам больше не нужны (поэтому у вас не будет много десятков таймеров, если кто-то спамит кнопку).

...