【问题标题】:Why does my timer keep running after timer.invalidate()?为什么我的计时器在 timer.invalidate() 之后继续运行?
【发布时间】:2019-01-17 23:26:21
【问题描述】:

制作 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() 显然不是让骰子停止滚动的方法。

有什么更好的方法来做到这一点?

提前感谢您的帮助!

【问题讨论】:

    标签: ios swift timer


    【解决方案1】:
    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 {
    }
    

    【讨论】:

    • 啊,就是这样!我只需要在 Timer.scheduledTimer 前面添加“timer =”...感谢您的帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-11-25
    • 1970-01-01
    • 1970-01-01
    • 2018-01-19
    • 2013-08-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多