How to make a SwiftUI function update the style of certain buttons based on @published class variables?

118 Views Asked by At

I want to have up to 13 buttons (the amount of total buttons should be able to change later based on user toggles), up to two per row/HStack. Each button will be a choice option for a game, only one is the correct answer. This game is an observable object class with several @published variables that keep track of the score, have a set of possible answers, get the correct answer per round that the buttons will use to know which one is correct, and to keep track of what state the game is in--whether the buttons were just clicked on so it knows it is now in the review state where the user can see if they guessed correctly and have the layout of the buttons change accordingly (green for correct guess, red for wrong guess).

I want the buttons to have a default gray look, but after a button is pressed (a guess is made) I would like for that look to change to either red or green color based on if the button's label == the correct answer. One published variable is reviewState which when false it should display all the buttons as default gray, but when true it should show the correct button in green and the wrong one in red (if any). The game wont switch reviewState back to false until a separate play button is clicked, giving the player the ability to look over the answer.

I tried creating one long function to build these buttons, but I keep getting hit with errors (many "type '()' cannot conform to 'View'"s). The function should create these buttons to have actions that change review state to true on press and call back onto this same function to rebuild them, just now with the correct/incorrect layouts:

 func setButtons(gameAnswer : Answer, selectedButton : Int, reviewState : Bool, AnswerChoices : [String]) -> some View {

    let multiple = round(value: AnswerChoices.count, divisor: 2)
    var increment = 0
    if (reviewState == true) {
        ForEach(0..<multiple){ i in
            HStack{
                if(AnswerChoices.count - increment == 1){
                    if (AnswerChoices[increment] == gameAnswer.answer){
                        var spot = increment
                        Button("\(AnswerChoices[spot])"){
                            game.reviewState = true
                            setButtons(gameAnswer: game.answer, selectedButton: spot, reviewState: game.reviewState, AnswerChoices: game.AnswerChoices)
                        }
                        .buttonStyle(CorrectButtonStyle())
                        increment += 1
                    }
                    else if (selectedButton == increment){
                        var spot = increment
                        Button("\(AnswerChoices[spot])"){
                            game.reviewState = true
                            setButtons(gameAnswer: game.answer, selectedButton: spot, reviewState: game.reviewState, AnswerChoices: game.AnswerChoices)
                        }
                        .buttonStyle(IncorrectButtonStyle())
                        increment += 1
                    }
                    else{
                        var spot = increment
                        Button("\(AnswerChoices[spot])"){
                            game.reviewState = true
                            setButtons(gameAnswer: game.answer, selectedButton: spot, reviewState: game.reviewState, AnswerChoices: game.AnswerChoices)
                        }
                        .buttonStyle(DefaultButtonStyle())
                        increment += 1
                    }
                }
                else {
                    ForEach(0..<2){ j in
                        if (AnswerChoices[increment] == gameAnswer.answer){
                            var spot = increment
                            Button("\(AnswerChoices[spot])"){
                                game.reviewState = true
                                setButtons(gameAnswer: game.answer, selectedButton: spot, reviewState: game.reviewState, AnswerChoices: game.AnswerChoices)
                            }
                            .buttonStyle(CorrectButtonStyle())
                            increment += 1
                        } else if (selectedButton == increment){
                            var spot = increment
                            Button("\(AnswerChoices[spot])"){
                                game.reviewState = true
                                setButtons(gameAnswer: game.answer, selectedButton: spot, reviewState: game.reviewState, AnswerChoices: game.AnswerChoices)
                            }
                            .buttonStyle(IncorrectButtonStyle())
                            increment += 1
                        }
                        else {
                            var spot = increment
                            Button("\(AnswerChoices[spot])"){
                                game.reviewState = true
                                setButtons(gameAnswer: game.answer, selectedButton: spot, reviewState: game.reviewState, AnswerChoices: game.AnswerChoices)
                            }
                            .buttonStyle(DefaultButtonStyle())
                            increment += 1
                        }
                    }
                }
            }
        }
    }
    else { //make all buttons default style
        ForEach(0..<multiple){ i in
            HStack{
                if(AnswerChoices.count - increment == 1){
                    var spot = increment
                    Button("\(AnswerChoices[spot])"){
                        game.reviewState = true
                        setButtons(gameAnswer: game.answer, selectedButton: spot, reviewState: game.reviewState, AnswerChoices: game.AnswerChoices)
                    }
                    .buttonStyle(DefaultButtonStyle())
                    increment += 1
                }
                else {
                    ForEach(0..<2){ j in
                        var spot = increment
                        Button("\(AnswerChoices[spot])"){
                            game.reviewState = true
                            setButtons(gameAnswer: game.answer, selectedButton: spot, reviewState: game.reviewState, AnswerChoices: game.AnswerChoices)
                        }
                        .buttonStyle(DefaultButtonStyle())
                        increment += 1
                    }
                }
            }
        }
    }
}

}

The multiple variable is used to find out how many HStacks/rows need to be made for the buttons, and the AnswerChoices.count - increment == 1 tells me if there will only be one button in a row since it is the last one (i.e. 13 answer choices would have 7 rows, 6 rows of 2 buttons with one row of 1). Increment variable is used to keep track of what number of buttons has been made, since I had to split up the ForEach loops to create new HStacks (it is set so that it matches with AnswerChoices[], first button = 0). "game" is the StateObject instance of the class. All the inputs to the function are published variables from the class, except for the selectedButton, which would just be the spot of the button that was clicked on. This is so that in case it was a wrong guess it knows which button to show in red. The CorrectButtonStyle changes it to green, the IncorrectButtonStyle changes it to red, and the DefaultButtonStyle has it gray.

Why am I getting hit with those errors? How do I make the function conform to View? Sorry for the super long post. I am new to Swift, and it is very possible I am overthinking this and that there is a much simpler way. Any help at all or any suggestions for how to achieve my goal would be greatly appreciated! Thank you!

0

There are 0 best solutions below