UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

Day 21 - A few questions

Forums > 100 Days of SwiftUI

Good day all!

I have some questions about the 21st day

Here is my code:

struct ContentView: View {
    @State private var showingScore = false
    @State private var ScoreTitle = ""
    @State private var Score = Int()

    @State private var countries = ["Estonia", "France", "Germany", "Ireland", "Italy", "Monaco", "Nigeria", "Poland", "Russia", "Spain", "UK", "US"].shuffled()
    @State private var correctAnswer = Int.random(in: 0...2)

    var body: some View {
        ZStack {
            Color.blue
                .ignoresSafeArea()

            VStack(spacing: 30) {
                VStack {
                    Text("Tap the flag of")
                        .foregroundColor(.white)
                    Text(countries[correctAnswer])
                        .foregroundColor(.white)
                }

                ForEach(0..<3) { number in
                    Button {
                        flagTapped(number)
                    } label: {
                        Image(countries[number])
                            .renderingMode(.original)
                    }
                }
            }
        }
        .alert(ScoreTitle, isPresented: $showingScore) {
            Button("Continue", action: askQuestion)
        } message: {
            Text("Your score is \(Score)")
        }
    }

    func flagTapped(_ number: Int) {

        if number == correctAnswer {
            ScoreTitle = "Correct"
            Score += 1
        } else {
            ScoreTitle = "Wrong"
        }

        showingScore = true
    }

    func askQuestion() {
        countries.shuffled()
        correctAnswer = Int.random(in: 0...2)
    }

}
  1. I don't quite understand why "number in" was used here after "ForEach (0 .. <3). Could someone explain it to me
ForEach(0..<3) { number in
                    Button {
                        flagTapped(number)
                    } label: {
                        Image(countries[number])
                            .renderingMode(.original)
                    }
                }
  1. Why ".alert" modifier is attached to Zstack?

  2. In function flagTapped, "If number == correctAnswer" I don't understand how it works ? How is it related?

    func flagTapped(_ number: Int) {
    
        if number == correctAnswer {
            ScoreTitle = "Correct"
            Score += 1
        } else {
            ScoreTitle = "Wrong"
        }
    
        showingScore = true
    }

2      

Maybe this will help

As for the .alert being attached to the ZStack, it could have just as easily been attached to the VStack, or the Button, or the Color. It is one of the modifiers that can be assigned to Views (ZStack, VStack, Color and Button are all defined as View types).

number == correctAnswer

works because the ForEach creates a number of views (for the buttons) and associates each view with the number from number in (actually it creates a tag for the view and links them). When you tap on the image of a flag, it triggers the operation in the closure { … } and passes the number (for that View) to the function flagTapped.

2      

One more question :)

  1. What determines the appearance of a good answer in this fragment of the code?
 ForEach(0..<3) { number in
                        Button {
                            flagTapped(number)
                        } label: {
                            Image(countries[number])
                                .renderingMode(.original)
                                .clipShape(Capsule())
                                .shadow(radius: 50)
                        }
                    }

The rest of the code:

func flagTapped(_ number: Int) {

        if number == correctAnswer {
            ScoreTitle = "Correct"
            Score += 1
        } else {
            ScoreTitle = "Wrong, That's flag of \(countries[number])"
        }

        showingScore = true
    }

Because I still don't get it

2      

The Button passes the value of number (corresponding the flag tapped because of the linked tag) to the function flagTapped.

In flagTapped

if number == correctAnswer {

is the check for the good answer.

func flagTapped sets the boolean showingScore, which is a State variable, therefore is being watched for changes.

The .alert sees the change of the state of showingScore which triggers it to perform its actions (present the Continue Button and show the current score).

2      

I like to think of ForEach as a View factory. You are going to feed some raw bits and pieces into the factory, and the factory is going to create some Views for your application!

So look at this code as the instructions to a factory. And ask yourself, What kind of views is this factory going to make?

// This is a view factory! What kind of views is it going to make?
ForEach(0..<3) { number in
    Button {  //  <----- Here's the answer!  This ForEach factory will make Buttons! A valid type of view....
        flagTapped(number)
    } label: {
        Image(countries[number])
            .renderingMode(.original)
            .clipShape(Capsule())
            .shadow(radius: 50)
    }
}

Next question to ask yourself.... How many buttons is this factory going to make?

ForEach(0..<3) { number in   //  <----- Here's the answer!  This ForEach factory will make three buttons  (0, 1, and 2)
    Button { 
        flagTapped(number)

This ForEach factory is given a range as its parameters. For each integer in this range, the ForEach factory will make ONE button.

In iOS applications, buttons usually have a label and will perform some action when tapped by your user! So ask yourself these final two questions:

  1. What is the label for the button?
  2. What does this button do when it is tapped?
Button {  
        flagTapped(number)  // <-- Here's the answer to question 2. When tapped it runs this function.
    } label: {
        Image(countries[number])  // <-- Here's the answer to question 1. This is the button's label.
            .renderingMode(.original)
            .clipShape(Capsule())
            .shadow(radius: 50)
    }

You can see from the code that the Button's label is a simple Image. Which image? You have many flag images in your application. But your game only uses the first THREE flags in the countries array. Each time you start a new game you tell the array to shuffle itself.

So as the ForEach factory builds a Button, it uses the number you provided ( number in ), and picks the appropriate flag image.

When the player presses a flag button, it executes the flagTapped(number)function. Again, it uses the number (0, 1, or 2) that was provided by the ForEach factory when the button was created.

2      

Hacking with Swift is sponsored by Essential Developer

SPONSORED Join a FREE crash course for mid/senior iOS devs who want to achieve an expert level of technical and practical skills – it’s the fast track to being a complete senior developer! Hurry up because it'll be available only until April 28th.

Click to save your free spot now

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.