How to create alerts on conditionals in SwiftUI?

Hi! I’m new to SwiftUI and coding in general and finished the new War Card game app. Is there a simple way to add an if statement with an alert? For those of you who don’t know, the War Card Game is his newest series he uploaded to Youtube. You click the “Deal” button and this function performs…

        // Randomize the players card
        var playerCardValue = Int.random(in: 2...14)
        var cpuCardValue = Int.random(in: 2...14)
        playerCard = "card" + String(playerCardValue)
        // Randomize the CPU's card
        cpuCard = "card" + String(cpuCardValue)
        // Update the score
        if playerCardValue > cpuCardValue {
            playerScore += 1
        }
        else if cpuCardValue > playerCardValue {
            cpuScore += 1
        }

I wanted to elaborate on his code and make a way to end the game. I decided that the first to reach 20 points would win. Once a player reached 20 points, I wanted to modify the function (which is called each time the player hits the “Deal” button) to reset back to 0. Hence the following excerpt from inside the Deal() function.

if playerScore > 19 || cpuScore > 19 {
    playerScore = 0
    cpuScore = 0
}

But I also wanted to create an alert telling you if you win or lose. In short, I wanted a function like

func deal() {
        // Randomize the players card
        var playerCardValue = Int.random(in: 2...14)
        var cpuCardValue = Int.random(in: 2...14)
        playerCard = "card" + String(playerCardValue)
        // Randomize the CPU's card
        cpuCard = "card" + String(cpuCardValue)
        // Update the score
        if playerCardValue > cpuCardValue {
            playerScore += 1
        }
        else if cpuCardValue > playerCardValue {
            cpuScore += 1
        }
        if playerScore > 19 || cpuScore > 19 {
            playerScore = 0
            cpuScore = 0
            }
        if playerScore > 19 {
            //Show alert
        }
        else if cpuScore > 19 {
            //Show another alert
        }
   }

And include a similar statement for if the player wins. That would all be in the Deal function, the function that is called when the player hits the deal button. So in addition to dealing cards, comparing them and updating the scores, it’ll check to see if a player has enough points to win. The problem is, I don’t know how to put an alert in an if statement. Everything I can find from google tells me to write some somewhat complicated code involving the creation of another State Bool property, but most of it seems irrelevant to conditionals. When I try to copy what I find online, it gives me errors and I don’t know where to put everything (like I said I want the Deal function to evaluate it.)

I’ll include the full code for the app that Chris had me create below.

import SwiftUI

struct ContentView: View {
    @State var playerCard = "card7"
    @State var cpuCard = "card13"
    @State var playerScore = 0
    @State var cpuScore = 0
    @State private var showingAlert = false
    var body: some View {
        
        ZStack {
            Image("background-plain")
                .resizable()
                .ignoresSafeArea()
            VStack{
                
                Spacer()
                Image("logo")
                Spacer()
                
                
                HStack {
                    Spacer()
                    Image(playerCard)
                    Spacer()
                    Image(cpuCard)
                    Spacer()
                }
                
                
                Spacer()
                
                
                
                
                Button {
                    deal()
                } label: {
                    Image("button")
                }
                
                
                Spacer()
                
                
                HStack {
                    Spacer()
                    VStack {
                        Text("Player")
                            .font(.headline)
                            .padding(.bottom, 10.0)
                        Text(String(playerScore))
                            .font(.largeTitle)
                    }
                    
                    Spacer()
                    VStack {
                        Text("CPU")
                            .font(.headline)
                            .padding(.bottom, 10.0)
                        Text(String(cpuScore))
                            .font(.largeTitle)
                    }
                    Spacer()
                }
                
                .foregroundColor(.white)
                Spacer()
            }
        }
    }
    
    func deal() {
        // Randomize the players card
        var playerCardValue = Int.random(in: 2...14)
        var cpuCardValue = Int.random(in: 2...14)
        playerCard = "card" + String(playerCardValue)
        // Randomize the CPU's card
        cpuCard = "card" + String(cpuCardValue)
        // Update the score
        if playerCardValue > cpuCardValue {
            playerScore += 1
        }
        else if cpuCardValue > playerCardValue {
            cpuScore += 1
        }
            }
    
    
        }
        
    
    
    struct ContentView_Previews: PreviewProvider {
        static var previews: some View {
            ContentView()
        }
    }

Hey @tylvaughan, I don’t think you can put it inside an if-else conditional if it’s something you’re looking for.

The approach that I’ll share to you is kind of similar to what you found from Google search results, but I’ll explain how and why. You’ll still be using boolean state variables to drive the presentation of alerts, but the solution is pretty simple. You need to use the bool state variables inside your if/else conditions so that your app knows which alert to show for a player win or a CPU win.

Step 1: Add Bool @State properties

First you need to declare the boolean state properties inside your code:

struct ContentView: View {
    @State var playerCard = "card7"
    @State var cpuCard = "card13"
    @State var playerScore = 0
    @State var cpuScore = 0
    @State private var showingAlert = false

    // Add these ----
    @State private var isPlayerWin = false
    @State private var isCpuWin = false

Step 2: Add alerts at the bottom of your ZStack

You will need two alerts, one would be an alert if the player wins, and another alert if the CPU wins

struct ContentView: View {
    ...
    var body: some View {
        ...
        ZStack {
            ...
        }
        .alert("Player wins!", isPresented: $isPlayerWin, actions: {
            Button {
                isPlayerWin = false
                isCpuWin = false
            } label: {
                Text("Congratulations!")
            }
        })
        .alert("CPU wins!", isPresented: $isCpuWin, actions: {
            Button {
                isPlayerWin = false
                isCpuWin = false
            } label: {
                Text("Try again!")
            }
        })
    }
    ...
}

Step 3: Show the alert if either the player or the CPU wins

For this step, you need to update the deal() function to use the Bool state properties

struct ContentView: View {
    ...
    var body: some View { ... }
    ...
    func deal() {
        // Randomize the players card
        var playerCardValue = Int.random(in: 2...14)
        var cpuCardValue = Int.random(in: 2...14)
        playerCard = "card" + String(playerCardValue)
        // Randomize the CPU's card
        cpuCard = "card" + String(cpuCardValue)
        // Update the score
        if playerCardValue > cpuCardValue {
            playerScore += 1
        }
        else if cpuCardValue > playerCardValue {
            cpuScore += 1
        }
        if playerScore > 19 || cpuScore > 19 {
            playerScore = 0
            cpuScore = 0
        }
        
        // !!!!!!! This is where you'll use the @State properties to show the alert
        if playerScore > 19 {
            isPlayerWin = true
        }
        else if cpuScore > 19 {
            isCpuWin = true
        }
    }
2 Likes

Thanks so much @inaki! It works!