Search code examples
iosswiftuiswiftui-button

SwiftUI Buttons meant to increment or decrement score, does so with the value of OTHER buttons almost exclusively


I have five buttons in swiftUI, that are meant to increase or decrease a displayed score, based on the response to an alert with two options, triggered on button press.

When pressing the button associated with a 200 point value, and responding to the alert, will result in an increment or decrement of the score of any other button. 400, 600, 800, and 100.

The increment or decrement is always correct, if you respond that you answer the question correctly, your score will always increase, just by a random amount. Same goes for getting the quetion wrong.

'CurrentGameStatus' is just a class, with a published variable for 'score'.

struct ContentView: View {
    @State private var showingAlert = false
    @ObservedObject var gameStatus = CurrentGameStatus()
    
    var body: some View {
        NavigationStack {
            HStack {
                VStack {
                    ScoreHeader(gameStatus: gameStatus)
                    
                    Button(action: { gameStatus.score = 0}) {
                        Text("Reset Score")
                    }
                    
                    Button(action: { showingAlert = true }) { Text("200") }
                        .buttonStyle(QuestionValueButtonStyle())
                        .alert("Did you get the question right?", isPresented: $showingAlert) {
                            Button("Yes") { gameStatus.score += 200 }
                            Button("No") { gameStatus.score -= 200 }
                        }
                    
                    Button(action: { showingAlert = true }) { Text("400") }
                        .buttonStyle(QuestionValueButtonStyle())
                        .alert("Did you get the question right?", isPresented: $showingAlert) {
                            Button("Yes") { gameStatus.score += 400 }
                            Button("No") { gameStatus.score -= 400 }
                        }
                    
                    Button(action: { showingAlert = true }) { Text("600") }
                        .buttonStyle(QuestionValueButtonStyle())
                        .alert("Did you get the question right?", isPresented: $showingAlert) {
                            Button("Yes") { gameStatus.score += 600 }
                            Button("No") { gameStatus.score -= 600 }
                        }
                    
                    Button(action: { showingAlert = true }) { Text("800") }
                        .buttonStyle(QuestionValueButtonStyle())
                        .alert("Did you get the question right?", isPresented: $showingAlert) {
                            Button("Yes") { gameStatus.score += 800 }
                            Button("No") { gameStatus.score -= 800 }
                        }

I've tried using environment objects, state objects, and observed objects, none achieve the desired result.


Solution

  • It looks like you're using the same boolean for all four alerts. So when you tap any of the four buttons, it's the same showingAlert state property that is being set to true. All of the alert modifiers that you have are using that value to determine if they should be presented or not. So you're actually trying to show all four alerts at the same time, but SwiftUI (or the UIAlertController behind the scenes) is only showing one of them. Try something like this:

    
    struct ContentView: View {
        @State private var showingAlert1 = false
        @State private var showingAlert2 = false
        @State private var showingAlert3 = false
        @State private var showingAlert4 = false
        @ObservedObject var gameStatus = CurrentGameStatus()
        
        var body: some View {
            NavigationStack {
                HStack {
                    VStack {
                        ScoreHeader(gameStatus: gameStatus)
                        
                        Button(action: { gameStatus.score = 0}) {
                            Text("Reset Score")
                        }
                        
                        Button(action: { showingAlert1 = true }) { Text("200") }
                            .buttonStyle(QuestionValueButtonStyle())
                            .alert("Did you get the question right?", isPresented: $showingAlert1) {
                                Button("Yes") { gameStatus.score += 200 }
                                Button("No") { gameStatus.score -= 200 }
                            }
                        
                        Button(action: { showingAlert2 = true }) { Text("400") }
                            .buttonStyle(QuestionValueButtonStyle())
                            .alert("Did you get the question right?", isPresented: $showingAlert2) {
                                Button("Yes") { gameStatus.score += 400 }
                                Button("No") { gameStatus.score -= 400 }
                            }
                        
                        Button(action: { showingAlert3 = true }) { Text("600") }
                            .buttonStyle(QuestionValueButtonStyle())
                            .alert("Did you get the question right?", isPresented: $showingAlert3) {
                                Button("Yes") { gameStatus.score += 600 }
                                Button("No") { gameStatus.score -= 600 }
                            }
                        
                        Button(action: { showingAlert4 = true }) { Text("800") }
                            .buttonStyle(QuestionValueButtonStyle())
                            .alert("Did you get the question right?", isPresented: $showingAlert4) {
                                Button("Yes") { gameStatus.score += 800 }
                                Button("No") { gameStatus.score -= 800 }
                            }