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

Day 35 Challenge

Forums > 100 Days of SwiftUI

I'm struggling with a portion of the Multiplication game and think I may have a basic misunderstanding of what is going on. My approach has been to create a struct for a Question (multiplicands and answers), then an array of random questions corresponding to the parameters. For each round, then, I would pop the last Question off the array and compare the user input to the answer and update score. Seemed straightforward.

Problem I'm having is that whenever I try to initialize the first question as var q : Question = questions.popLast() in some form, I get into a spot where Swift tells me that I'm trying to use a property initializer before self is available. I've tried changing it to be in a function, in a closure, using lazy or even an init function all to no avail. Help!

import SwiftUI

struct Question {
    var num1 : Int
    var num2 : Int
    var answer : Int

struct ContentView: View {

    @State private var maxNumber = 20
    @State private var numberOfQuestions = 10
    @State public var questions = [Question]()
    @State public var answer = ""
    @State public var showingSheet = true
    @State public var playerScore = 0
    @State public var q : Question = nextQuestion() // getting error here: swiftui property initializers run before 'self' is available

    var body: some View {
        NavigationView {
            ZStack {
                LinearGradient(gradient: Gradient(colors: [.blue, .black]), startPoint: .top, endPoint: .bottom)
                VStack {
                    Image(systemName: "square")
                        .shadow(radius: 2.0)
                    Text("What is")
                        .shadow(radius: 2.0)
                    Text("\(q.num1) X \(q.num2)?")
                    // Text("3 X 5?")
                        .shadow(radius: 2.0)
                    TextField("Answer?", text: $answer)


            .sheet(isPresented: $showingSheet) {
                Form {
                    Text("Start a new game")
                    Stepper("Highest Multiple Number:\n\(maxNumber)", value: $maxNumber)
                    Stepper("Number of Questions:\n\(numberOfQuestions)", value: $numberOfQuestions)
                    Button("Start Game") {
                        generateQuestions(max: maxNumber, number: numberOfQuestions)
                        // q = nextQuestion()
        .toolbar {
            ToolbarItemGroup(placement: .bottomBar) {
                Text("Score: \(playerScore)")
                Button {
                } label: {
                    Image(systemName: "gear")

    func generateQuestions(max : Int, number : Int) {
        for _ in 1...number {
            var first = Int.random(in: 2...max)
            var second = Int.random(in: 2...max)
            var product = first * second
            var newQuestion = Question(num1: first, num2: second, answer: product)
            print(first, second, product)
         // var q = questions.popLast()!
    mutating func nextQuestion() -> Question {
        let question = questions.popLast()
        return (question)!

    func isCorrect(q: Question, a: Int) -> Bool {
        return a == q.answer


You're almost there.

  1. Assign a default Question to q, maybe Question(num1: 0, num2: 0, answer: 0)
  2. Uncomment the q = nextQuestion() line
  3. nextQuestion() doesn't mutate anything in the struct, so don't mark it as mutating

Note: Instead of assigning a default Question to q, you could make q an optional. That would require a few more tweaks elsewhere in your code. Either way would work in the end, though.

And another note: The way you are generating the questions array includes the possibility of duplicate questions. If you don't want duplicate questions, you will need to adjust your approach.


Thanks so much for your help, that did it! Your point about dupe questions is a good one. My thought was to create the entire pool of possible questions (iteration) and then randomly pick n from the pool. On my to-do list!


Thanks for this thread. Very helpful when I got stuck.


Hacking with Swift is sponsored by Fernando Olivares

SPONSORED Fernando's book will guide you in fixing bugs in three real, open-source, downloadable apps from the App Store. Learn applied programming fundamentals by refactoring real code from published apps. Hacking with Swift readers get a $10 discount!

Read the book

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

Reply to this topic…

You need to create an account or log in to reply.

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.