Home > Blockchain >  Why is the alert triggering out of order if value is not updated?
Why is the alert triggering out of order if value is not updated?

Time:12-13

I have the following alerts:

    .alert(scoreTitle, isPresented: $showingScore) {
        Button("Continue", action: askQuestion)
    } message: {
        Text("Your score is \(totalCorrectAnswers)")
    }
    .alert("Game Over", isPresented: $showingGameOver) {
        Button("Play Again", action: resetGame)
    } message: {
        Text("Your total score was \(totalCorrectAnswers)")
    }

Note how they are triggered by showingScore and ShowingGameOver

The alerts come into play when the following event handler is called

func flagTapped(_ number: Int) {
    if number == correctAnswer {
        scoreTitle = "Correct!"
        totalCorrectAnswers  = 1
        
    } else {
        scoreTitle = "Wrong! That was the flag of \(countries[number])"
        totalCorrectAnswers  = 0
    }
    showingScore.toggle()
    attempts  = 1
    
    if attempts == maxAttempts {
        showingGameOver.toggle()
    }
}

As you can see, first the answer is checked and depending if the answer is correct or false, a different message will be displayed in the first alert. If we hit the limit of attempts, another alert comes right after and resets the game.

The problem I had was that if the last attempt was incorrect, the alerts would show out of order. Initially, I did not have this line totalCorrectAnswers = 0, but I guessed (correctly) it might be necessary in order to get the alerts to trigger in the right. My guess is that this was fixed because totalCorrectAnswers is a state property and it triggers a refresh, but it doesn't really explain why this was needed.

CodePudding user response:

Using a tuple variable and a method that staggers the alerts is one approach.

You need the staggering because you can't present one alert above the other reliably such as getting the wrong answer and game over at the same time.

import SwiftUI

@available(iOS 15.0, *)
struct AlertSampleView: View {
    //One variable controls the single alert
    @State var alertVariable:(title:String,isPresented: Bool, actionTitle: String ,action: () -> Void,message: String) = ("",false,"OK",{},"")
    //MARK: Sample variables based on provided code
    @State var correctAnswer = 1
    @State var totalCorrectAnswers = 1
    @State var attempts = 1
    @State var maxAttempts = 2
    var body: some View {
        Button("answer", action: {
            //Mimic result
            flagTapped(Int.random(in: 0...2))
        })
        //Single alert
            .alert(alertVariable.title, isPresented: $alertVariable.isPresented, actions: {
                Button(alertVariable.actionTitle, action: alertVariable.action)
            }, message: {
                Text(alertVariable.message)
            })
    }
    func flagTapped(_ number: Int) {
        if number == correctAnswer {
            scheduleAlert(title: "Correct!")
            
            totalCorrectAnswers  = 1
            attempts = 0
            
        } else {
            scheduleAlert(title: "Wrong! That was the flag of ...")
            attempts  = 1
        }
        if attempts == maxAttempts {
            scheduleAlert(title: "Game Over")
        }
    }
    //Staggers the presentation of the alerts
    func scheduleAlert(title: String, count:Int = 0){
        //Delay Alert if there is one on the screen
        if alertVariable.isPresented{
            //After 5 secondsish dismiss what is there
            if count >= 25{
                alertVariable.isPresented = false
            }
            //This delay leaves a little gap between alerts
            DispatchQueue.main.asyncAfter(deadline: .now()   0.2) {
                scheduleAlert(title: title, count: count   1)
            }
        }else{
            alertVariable.title = title
            alertVariable.isPresented = true
        }
    }
}

@available(iOS 15.0, *)
struct AlertSampleView_Previews: PreviewProvider {
    static var previews: some View {
        AlertSampleView()
    }
}
  • Related