WWDC24 SALE: Save 50% on all my Swift books and bundles! >>

SOLVED: Stuck on day 34 after scoring 12/12 on quiz

Forums > 100 Days of SwiftUI

I just got 12/12 on the quiz for day 34 (Project 6, part 3). https://www.hackingwithswift.com/100/swiftui/34

And, I just went over my extensive notes from yesterday.

I googled on every related phrase I could think of and did not understand any of the code provided as solutions.

Apparently I'm competely stuck. When did he show us how do do any of this? Thanks

2      

I'm not sure what "code provided as solutions" you are referring to. But the challenges are all based on concepts you learned in project 6.

In challenge 1 for example

"When you tap a flag, make it spin around 360 degrees on the Y axis."

Paul provided an example in project 6 for how make a view spin 360 degrees using rotation3DEffect

.rotation3DEffect(.degrees(animationAmount), axis: (x: 0, y: 1, z: 0))

He also provided an example of how to change an animatable value based on certain condition being true

.clipShape(RoundedRectangle(cornerRadius: enabled ? 60 : 0))

You will have to combine those two concepts to complete this challenge.

The biggest road block on this challenge for me was figuring out how to only set the rotationAmount for the button that was tapped, and not the other buttons. But I realized that the reason I was so confused was because we weren't actually storing a variable anywhere to keep track of which button was tapped yet. So, you may have to create one.

2      

I'm not sure what "code provided as solutions" you are referring to

I just meant the random similar stuff one finds when searching on code topics. I couldn't find any specific examples.

@Fly0strich Thanks! I found the 3D effect modifier in my notes. I missed the one that takes a variable. But, how in the world would a ternary fit in the 3D method?

He seems to say that the 3D modifier is an explicit modifier and the other kind is implicit. I'm not sure how they go together.

And, where do they even go? On the view we made for the image? On the button? Both?

And, then the logic seems so complicated. We need one button to stay large and spin and the other two to do something else? That seems like it would require another function and I'm not even comfortable with these mysterious modifiers yet. And, there's no reference for any of these modifiers. And, xcode isn't exactly an open book about them either.

All I can think to do is go back and watch all the videos for yesterday again. Maybe something will click now that I know what the project is.

2      

Save 50% in my WWDC sale.

SAVE 50% To celebrate WWDC24, all our books and bundles are half price, so you can take your Swift knowledge further without spending big! Get the Swift Power Pack to build your iOS career faster, get the Swift Platform Pack to builds apps for macOS, watchOS, and beyond, or get the Swift Plus Pack to learn advanced design patterns, testing skills, and more.

Save 50% on all our books and bundles!

Right away, in the first video, I'm getting reminded of how to toggle a state from a button.

It gave me an idea since we need to store which button was clicked.

 @State private var selected = -1

Then down in the flagTapped function I can store the tapped flag number in state now.

    // Check if chosen flag number matches correctAnser
    func flagTapped(_ number: Int) {
        if number == correctAnswer {
            scoreTitle = "Correct"
            score += 1
        } else {
            scoreTitle = "Incorrect. You chose \(countries[number])"
        }
        turns -= 1
        selected = number
        // Check if turns is zero and game is over
        if (turns == 0) {
            showingScore = false
            showingFinalScore = true
        } else {
            showingScore = true
        }

    }
// Debug
                Text("\(selected)")

Seems to work. Now how do I use it... to be continued.

2      

Yep, it looks like you're catching on.

Now it's just a matter of finding where to put the

.rotation3DEffect(.degrees(animationAmount), axis: (x: 0, y: 1, z: 0))

Basically, which view do you want the rotation effect to be applied to?

And then, what do you want the animationAmount to actually be set to? Is it conditional based on... something?

Also, remember, now that you are storing which button is selected. You will probably need to reset it as each new question is asked, so that it doesn't try to use the answer that was already given for the last question.

2      

Seems I must have been so focused on the following videos I didn't realize the significance of this first one.

My second clue is that the solution probably has something to do with using multiple stacked implicit animations with one of them returning nil.

But, I still can't wrap my head around how that would work. Maybe a little trial and error will get me there.

But, I'd prefer to have a better understanding of what we're doing to be frank.

2      

I think the problem with this challenge is that the view we want to apply the rotation effect to is being created inside a ForEach loop. But, we only want one of the buttons created by the ForEach to have the rotation effect. (The button that was tapped)

So, remember the other example that I mentioned above...

.clipShape(RoundedRectangle(cornerRadius: enabled ? 60 : 0))

This sets the cornerRadius value of a RoundedRectange to be 60 or 0 based on enabled being true or false.

In our case, we want to use this animation modifier on the button in the ForEach loop...

.rotation3DEffect(.degrees(animationAmount), axis: (x: 0, y: 1, z: 0))

But, we don't want animationAmount to be the same for every button in the ForEach loop. So, how can we replace animationAmount with one value for the button that was tapped, and another value for the buttons that weren't tapped?

3      

But, we don't want animationAmount to be the same for every button in the ForEach loop. So, how can we replace animationAmount with one value for the button that was tapped, and another value for the buttons that weren't tapped?

Thank you. It seems like that would clear things up if I understood any of this.

I went and coded myself into a corner today.

After storing the clicked flag number in state, it seemed like it needed to get passed into the flag's view.

 Button {
            withAnimation() {
                animationAmount += 360
            }
            flagTapped(number)
        } label: {
            FlagImage(flagName: countries[number], selected: selected, number: number, animationAmount: animationAmount)
        }

Then in the view I was able to print out different text for the clicked flag. Seemed like progress.

// Create a View for each individual flag
struct FlagImage: View {
    var flagName: String
    let selected: Int
    let number: Int
    let animationAmount: Double

    var body: some View {
        Image(flagName)
            .renderingMode(.original)
            .clipShape(Rectangle())
            .shadow(radius: 5)
        if (selected == number) {
            //Text("\(selected)")
            .rotation3DEffect(.degrees(animationAmount), axis: (x: 0, y: 1, z: 0))
        } else {
            Text("not selected")
        }
    }
}

But, now it seems I can't just apply modifiers based on an if statement in the view.
Error: Cannot infer contextual base in reference to member 'rotation3DEffect'

I wonder when I lost the thread in this course? I thought I was doing well and understood everything up to this point.

2      

Just had a thought. Could it be as simple as something like:

.rotation3DEffect(.degrees(selected == number ? 360 : 0), axis: (x: 0, y: 1, z: 0))

???

I suppose maybe I'll do a little more tinkering today after all.

2      

Yes, this is the way I was trying to suggest. Although, in your previous code snippet, it looks like you are trying to apply the rotation to the image in the FlagImage struct, rather than the actual button in your ContentView.

2      

Don't get too discouraged about not figuring out this challenge immediately though. In my opinion, this is probably one of the most difficult challenges to figure out in the whole 100 days course. I didn't even complete it until after I had finished the 100 days and came back to look at it again later.

3      

Holy carp, this sure is simpler. But, it has weird behavior. It works right the first time. Then it won't spin if clicking on the same flag number as last time. And, it spins more than one flag, the next closest it looks like, when clicking another flag number.

 ForEach(0..<3) { number in
      Button {
          flagTapped(number)
          enabled.toggle()
      } label: {
          FlagImage(flagName: countries[number])
      }
      .rotation3DEffect(.degrees(selected == number ? 360 : 0), axis: (x: 0, y: 1, z: 0))
      .animation(.default, value: enabled)
  }

2      

Don't get too discouraged about not figuring out this challenge immediately though. In my opinion, this is probably one of the most difficult challenges to figure out in the whole 100 days course. I didn't even complete it until after I had finished the 100 days and came back to look at it again later.

Thanks, maybe I'll just skip today then. I don't think I was even getting close.

2      

OMG it almost worked:

 .rotation3DEffect(.degrees(selected == number && enabled == true ? 360 : 0), axis: (x: 0, y: 1, z: 0))

Added && enabled == true

It only worked for the first couple of times and then started spinning the wrong flag.

2      

I got it! I got rid of the && enabled == true. That was a shot in the dark anyway.

When I thought about it some more I realized I just needed to reset the selected var in the askQuestion function.

And poof, it works. Whew

A million thanks @Fly0strich !!! I don't think I would have gotten there anytime soon without your guidance.

3      

My code was similar to that, yet wasn't working. So I came here and everything looks the same but,,, it isn't working.

I probably went wrong somewhere, could you show the full solution?

2      

Save 50% in my WWDC sale.

SAVE 50% To celebrate WWDC24, all our books and bundles are half price, so you can take your Swift knowledge further without spending big! Get the Swift Power Pack to build your iOS career faster, get the Swift Platform Pack to builds apps for macOS, watchOS, and beyond, or get the Swift Plus Pack to learn advanced design patterns, testing skills, and more.

Save 50% on all our books and bundles!

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.