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

Milestone 3: Projects 4-6 -- cannot figure out how to use a struct inside ContentView

Forums > 100 Days of SwiftUI

Hi all,

I am trying to build an struct that would contain the database of answers as well as of the questions to the multiplication table challenge. I did the following inside of a playground and it works perfectly fine (or at least the way I intend it to:

import Cocoa

struct Question {
    var questions = [String]()
    var answers = [Int]()

    var questionsDatabase = [Array<String>]()
    var answersDatabase = [Array<Int>]()

    mutating func generateDatabase() {
        for i in 0...12 {
            for j in 0...i {
                questions.append("\(i) * \(j)")
                answers.append(i*j)
            }
            questionsDatabase.insert(questions, at: i)
            answersDatabase.insert(answers, at: i)
            questions.removeAll()
            answers.removeAll()
        }
    }

}

var ourTable = Question()
ourTable.generateDatabase()

print(ourTable.questionsDatabase[3]) // shows ["3 * 0", "3 * 1", "3 * 2", "3 * 3"]
print(ourTable.questionsDatabase[3][3]) // shows 3 * 3

However, if I try to get it to work inside my main project, it always crashes with a fatal error and I can see that questions, answers, questionsDatabase, answersDatabase all have 0 values - and I cannot for the life of me tell why... :(

import SwiftUI

struct MultiplicationTable {

    var questions = [String]()
    var answers = [Int]()

    var questionsDatabase = [Array<String>]()
    var answersDatabase = [Array<Int>]()

    mutating func generateDatabase() {
        for i in 0...12 {
            for j in 0...i {
                questions.append("\(i) * \(j)")
                answers.append(i*j)
            }
            questionsDatabase.insert(questions, at: i)
            answersDatabase.insert(answers, at: i)
            questions.removeAll()
            answers.removeAll()
        }
    }
}

struct ContentView: View {

    @State private var ourTable = MultiplicationTable()

    var body: some View {
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundStyle(.tint)
            Text(ourTable.questionsDatabase[3][3])
        }
        .onAppear {
            ourTable.generateDatabase()
        }
        .padding()
    }
}

#Preview {
    ContentView()
}

Any pointers would be highly appreciated! Thank you a ton in advance!

   

Hi, Could a solution be to add, if "not empty database" for displaying the text?

 if !ourTable.questionsDatabase.isEmpty {
           Text(ourTable.questionsDatabase[3][3])
 }

   

Hi Martin,

Thank you very much for your input. Indeed, that fixes everything :)

However, what I don't understand is why this is needed. I always assumed that everything inside of onAppear will be run first and only upon completion, the code inside of VStack gets executed. That's not the case then?

Thank you!

   

Hi,

Instead of onAppear, you can run the function with init in the structure. So the database is ready before you show the view.

init() {
        generateDatabase()
}

   

Thank you very much for your help. I think I am getting the hang of it...

1      

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!

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.