当按钮为 spammed/rapidly 并重复按下时,可能与 UIButton 操作中的 DispatchQueue.main.asyncAfter 有关的错误

Bug possibly related to DispatchQueue.main.asyncAfter in UIButton action when button is spammed/rapidly and repeatedly pressed

可以在此处克隆该项目https://github.com/randomjuniorburger/quizapp

我有一个 UIButton,它链接到一个使用 DispatchQueue.main.asyncAfter 的操作。该应用程序运行良好,除非用户发送垃圾邮件 True/False buttons/presses 或在短时间内连续多次触发它们中的任何一个,导致延迟重叠并允许用户获得更高的分数比应该可能的(例如,只有 8 个问题有答案 "True",但如果 true 按钮被发送垃圾邮件,则可能由于错误而得到 10 分)

我想知道如何 fix/prevent 这个?

注意 - 我是 beginner/hobbyist Swift 开发人员。这个项目是我尝试重新创建我正在上的 Angela Yu 课程的一个模块。

我欢迎任何关于如何改进我的代码并更严格地遵循最佳实践的建议。

单独按钮的代码是;

@IBAction func answerPressed(_ sender: UIButton) {

    let userAnswer = sender.currentTitle
    let actualAnswer = quizArray[questionNumber].answer

    if questionNumber < (quizArray.count - 1) {
        self.questionNumber += 1
        updateProgressBar()
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
            self.questionLabel.text = self.quizArray[self.questionNumber].text
        }

        if userAnswer == actualAnswer {
            questionLabel.text = "✅"
            score += 1
            scoreLabel.text = String("Score: \(score) / 12")

        } else {
            questionLabel.text = "❌"
        }

    } else if questionNumber == (quizArray.count - 1) && questionLabel.text != "End of Quiz" {
        if userAnswer == actualAnswer {
            questionLabel.text = "✅"
            score += 1
            scoreLabel.text = String("Score: \(score) / 12")
        } else {
            questionLabel.text = "❌"
        }

        DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
            self.progressBar.progress = Float(1)
            print("No more questions")
            self.questionLabel.text = "End of Quiz"
        }
    }

}

这是可能的解决方案 - 只是不要让用户产生不需要的点击

sender.isEnabled = false // don't allow action until question updated
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
    self.questionLabel.text = self.quizArray[self.questionNumber].text
    sender.isEnabled = true // << allow user interaction
}

秒后做同样的事情