The project can be cloned here https://github.com/randomjuniorburger/quizapp
I have a UIButton which is linked to an action which makes use of DispatchQueue.main.asyncAfter. The app works well except when the user spams the True/False buttons/presses or triggers either of them many times consecutively in a short interval, causing the delay(s) to overlap and allowing the user to achieve a higher score than should be possible (e.g. only 8 questions have the answer "True", but a score of 10 is possible due to the bug if the true button is spammed)
I am wondering how I can fix/prevent this?
NB - I am a beginner/hobbyist Swift developer. This project is my attempt to recreate a module of a course I am taking by Angela Yu.
I welcome any suggestions as to how my code can be improved and more closely follow best-practice.
The code for the button alone is;
@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"
}
}
}
Here is possible solution - just don't give possibility for a user to generate not desired taps
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
}
in second do the same