SwiftUI: How to initialize a variable dependent on another variable within a view

Viewed 951

I have a page that is supposed to get a custom "Topic" (a structure that contains a title, an image for the background, and an embedded list of questions in a string array), and then I want the view to also have a shuffled list of questions that are displayed in a card stack, and that should be a state variable so I can use an animation to slide cards off the list.

I've been trying to initialize the question array before the body, but I'm running into issues where "self is not available" in property initializers. So I tried initializing the question variable before the body, but that is also causing issues.

Then when I call this view other places in my code, it's looking for me to pass in a value for the currentQuestions parameter instead of the currentTopic parameter.

I want to link to the view where I just pass in a currentTopic, it creates the shuffled array based on that current Topic, and then I can display that. Is there a better way to set up these variables/initialize them?

struct TopicPage: View {
    //inherit current topic from the PackTopics page, and create a state variable that gets set to a random question.
    var currentTopic: Topic
    @State var currentQuestions: [String]
    

    init(currentQuestions: [String]) {
        getQuestionList()
    }
    
    func getQuestionList() {
        let newQuestionList: [String] = currentTopic.questions
        currentQuestions = newQuestionList.shuffled()
    }
    
    var body: some View {
        VStack {
            Text(currentTopic.name).fontWeight(.bold)
                .font(.title)
                .padding(20)
                .offset(x: 0, y: 50)
            ZStack {
                ForEach(0..<currentQuestions.count, id: \.self) { question in
                    QuestionBox(currentQuestion: self.currentQuestions[question])
                        .stacked(at: question, in: self.currentQuestions.count)
                }
1 Answers

Here is a way to go... because @State can be initialized with init arguments only via State constructor.

struct TopicPage: View {
    //inherit current topic from the PackTopics page, and create a state variable that gets set to a random question.
    var currentTopic: Topic
    @State var currentQuestions: [String]
    

    init(currentTopic, Topic, currentQuestions: [String]) {
        self.currentTopic = currentTopic

        // use this to initialize
        self._currentQuestions = State(initialValue: currentTopic.questions.shuffled())
    }
    
    func getQuestionList() {
        let newQuestionList: [String] = currentTopic.questions

        // use this to update
        self.currentQuestions = newQuestionList.shuffled()
    }
Related