为什么计时器在timer.invalidate()之后继续运行?

时间:2019-01-17 23:26:21

标签: ios swift timer

制作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()

我很困惑,因为每次我按下按钮时,标题都会按预期变化,这意味着变量“ state”在0和1之间正确地来回切换。但是,timer.invalidate()显然不是使骰子停止滚动的方法。

有什么更好的方法?

在此先感谢您的帮助!

1 个答案:

答案 0 :(得分:2)

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