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

SOLVED: Looking for clue for Day 35 challenge (Multiply!)

Forums > 100 Days of SwiftUI

I wish I could see a screenshot of a successful layout. I'm just really blocked on it. I've got a screen that does the quizzing part, and a trick to hide subviews, and I've learned about @ObservableObject so I can use that to pass data around, of which surprisingly little needs passing. (I think just the max integers to multiply, the number of questions, and the score.)

It's just the "how does the user use this thing" that has me blocked.

Thanks, community! bc

ps. What should I do if the user doesn't want to go again?

2      

You'll probably want to have a function to ask a question and a button linked to another function that checks their answer.

Every time they enter an answer and tap the "Check Answer" button, it would handle checking the answer, updating the score, etc, and calling the function to ask the next question.

Mine doesn't let them choose if they don't want to play again specifically. It just lets them know when the game is over. Then when they tap OK it takes them back to the settings selection screen where they can start a new game if they want to.

2      

ha1naux wonders:

What should I do if the user doesn't want to go again?

Take inspiration from other apps you use!

What do you do when you've finished texting a message to your mates?

What do you do when you haven't quite finished solving Wordle, but your bus arrives?

What do you do after paying for groceries with ApplePay ?

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!

Can someone post a screenshot? That would go a long way to clarifying things in my mind. Is the "selection" screen separate, and if so, how did you solve that?

Thanks, sorry to be a dunderhead

bc

2      

I'll show you how I set up my ContentView for now to give you some idea of how it can be done. You'll notice that I use two other custom views that I created, and you'll be able to see how their initializers are called. That should give you a pretty good idea of how to write the initializers for the other two views on your own. From there, you will basically just need to create the interfaces for the other two views the way you want them to be.

struct ContentView: View {
    @State private var gameStarted = false
    @State private var difficulty = 0
    @State private var numberOfQuestions = 0

    var body: some View {
        ZStack {
            if gameStarted {
                GameView(difficulty: difficulty, numberOfQuestions: numberOfQuestions, newGame: newGame)
            }

            if !gameStarted {
                SettingsView(startGame: startGame)
            }
        }
    }

    func startGame(difficulty: Int, numberOfQuestions: Int) {
        self.difficulty = difficulty
        self.numberOfQuestions = numberOfQuestions
        gameStarted = true
    }

    func newGame() {
        gameStarted = false
    }
}

(You may notice that I am not using @ObservableObject here. I am just using the method that Paul hints at for this challenge which involves passing closures between views.)

If you are still stuck, and you really want me to, I could show you my full code. I just hesitate to do this because these challenge projects are very important for gaining the skills to do things on your own. These are your only chances in the course to prove that you can create your own projects without just copying code that Paul gives you. So, I would strongly encourage you to do as much as you can without me showing you the solution.

4      

@Bnerd  

My silly way of doing it :P Pick a number, pick how many questions you want, just type your answer!

3      

Hey @Fly0strich thanks. Your code taught me how to use closures. The only thing I got really stuck on turned out to be:

                    .onSubmit {scoreAnswer()}

3      

To be clear, you can say:

.onSubmit(scoreAnswer)

or you can say:

.onSubmit {scoreAnswer()}

but I said:

.onSubmit(scoreAnswer())

and that caused SwiftUI to tell me to mark scoreAnswer() as mutating, which produced a world of confusion and pain. Don't be like me.

2      

2      

Hey @Fly0strich. Thanks for the ContentView code. I've completed the challenge using functions returning views to split into several views. Works fine, although not very 'elegant'.

I'm trying to follow Paul's hints to pass data through closures. I'm stuck in initializing the child views. I can't figure out how to use closures there. Could you please show how you did it in SettingsView or/and GameView. It would help me a lot.

Thanks for helping.

gc

2      

Hello,

@Fly0strich, I tried to find out how to use your given example on how to write the view, e.g. SettingsView based on the shown initializers. I tried it now for days, but don#T have an idea :-(

If you read this, can you please gib´ve me a hint on how to start writing e.g. the SettingsView?

Regards, Ralf

2      

Sorry, I haven't been very active in these forums lately.

But, if you look at this line of code from what I provided above...

SettingsView(startGame: startGame)

That should give you a pretty good idea of what the initializer for the SettingsView would look like. But, you'll have to keep in mind the hint that Paul gives about using escaping functions.

We want to pass in this function shown in my code above...

func startGame(difficulty: Int, numberOfQuestions: Int) {
    self.difficulty = difficulty
    self.numberOfQuestions = numberOfQuestions
    gameStarted = true
}

and will need to mark it as @escaping in the SettingsView initializer...

init(startGame: @escaping (Int, Int) -> Void) {
    self.startGame = startGame
}

You will want to have difficulty and numberOfQuestions properties in SettingsView as well, which can be modified by the user. (Those aren't shown in the initializer, because I gave them default values) Then, those can be used as parameters in the call to the startGame function.

Since we are using an escaping function, it makes it possible to have a button like this in the SettingsView

Button("Start") {
    startGame(difficulty, numberOfQuestions)
}

But the function won't actually run until it is back in the context of ContentView. That way, it is able to modify the difficulty, numberOfQuestions, and gameStarted properties in ContentView, while using the values that were selected in SettingsView.

You can do something similar in GameView. But we don't really need to pass any parameters to the function used in GameView. It just needs to be able to move back to the context of ContentView when it is called so that it can toggle the gameStarted value there.

Hopefully this helps.

2      

I used an action sheet for configuration, a subview for the selection of the answer, and a list to show the history of the games. I also tried to use a data model to store the configuration. Nice challenge. It took the most time so far. As you can tell, I didn't spend much time on the design. Here's the two main screenshots (play and configuration).

play screen config screen

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.