Почему мой таймер продолжает работать после timer.invalidate ()? - PullRequest
0 голосов
/ 18 января 2019

Создание игры Yatzee. У меня есть 5 изображений и кнопка на экране:

@IBOutlet var button: UIButton!
@IBOutlet var dice1: UIImageView!
@IBOutlet var dice2: UIImageView!
@IBOutlet var dice3: UIImageView!
@IBOutlet var dice4: UIImageView!
@IBOutlet var dice5: UIImageView!

Изображения в моей папке ресурсов называются Dice1.png, Dice2.png вплоть до Dice6.png.

При нажатии кнопки Int.random выбирает одно из шести изображений для отображения.

@IBAction func button(_ sender: Any) {
    dice1.image = UIImage(named: "Dice\(Int.random(in: 1...6))")
    dice2.image = UIImage(named: "Dice\(Int.random(in: 1...6))")
    dice3.image = UIImage(named: "Dice\(Int.random(in: 1...6))")
    dice4.image = UIImage(named: "Dice\(Int.random(in: 1...6))")
    dice5.image = UIImage(named: "Dice\(Int.random(in: 1...6))")
}

Работает отлично!

Вот моя проблема:

Я бы хотел, чтобы кости быстро просматривали изображения после первого касания (как если бы кости качались в чашке), а затем при повторном нажатии кнопки они должны перестать вращаться (как если бы их бросали). ).

Я думал сделать это с помощью таймера. Когда кнопка нажата, таймер срабатывает каждые 0,1 секунды, отображая другое изображение каждые 0,1 секунды.

var timer = Timer()
var state = 0

@IBAction func button(_ sender: Any) {
    if state == 0 {
        Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(roll), userInfo: nil, repeats: true)
        button.setTitle("Roll", for: UIControl.State.normal)
        state = 1
    } else {
        timer.invalidate()
        button.setTitle("Shake", for: UIControl.State.normal)
        state = 0
    }
}

@objc func roll() {
    dice1.image = UIImage(named: "Dice\(Int.random(in: 1...6))")
    dice2.image = UIImage(named: "Dice\(Int.random(in: 1...6))")
    dice3.image = UIImage(named: "Dice\(Int.random(in: 1...6))")
    dice4.image = UIImage(named: "Dice\(Int.random(in: 1...6))")
    dice5.image = UIImage(named: "Dice\(Int.random(in: 1...6))")
}

После первого нажатия кнопки все кубики меняются каждые 0,1 секунды, и это выглядит круто, а название кнопки меняется на «Бросить».

Когда кнопка нажата во второй раз, заголовок кнопки изменится на «Встряхнуть», как и ожидалось, но вместо того, чтобы остановиться, игральная кость начинает менять изображения в два раза быстрее, что, я думаю, означает, что таймер вызывается снова, вместо timer.invalidate ()

Я в замешательстве, потому что каждый раз, когда я нажимаю кнопку, заголовок меняется, как и ожидалось, и это означает, что переменная «состояние» правильно переключается между 0 и 1. Однако timer.invalidate (), очевидно, не способ заставить кости перестать катиться

Какой лучший способ сделать это?

Заранее спасибо за любую помощь!

1 Ответ

0 голосов
/ 18 января 2019
Timer.scheduledTimer(timeInterval...)

создает таймер и запускает его. Функция также возвращает таймер, который создан, но он нигде не сохраняется, поэтому вы не можете сделать его недействительным.

Ваша первая строка

var timer = Timer()

странно. Вы объявляете переменную и назначаете объект Timer, который был создан без каких-либо параметров. Этот объект совершенно бесполезен. Вы позже позвоните

timer.invalidate()

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

Полагаю, вы начали писать код, пока он не скомпилирован без ошибок. Вот что вы должны были сделать:

// Create an optional Timer variable, initially nil
var timer: Timer?

// Later: Store a scheduled timer
timer = Timer.scheduledTimer(timeInterval...)

// Invalidate if the timer exists and set to nil
timer?.invalidate()
timer = nil

Вы также можете избавиться от переменной «состояние» и просто проверить переменную таймера вместо состояния == 0

if timer == nil {
} else {
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...