I can’t understand why my array (which I checked to ensure it isn’t empty) is not being passed through to a view correctly.
ContentView receives the set of questions from MenuView, and once assigned to contentSelectedSet, I checked to make sure the two sets contained the correct information, which they do. The entire set of questions as I would expect is there. However, in the .fullScreenCover modifier, the set is not passed to DebugQuizView and will only take me to that else text. If I don’t use the if/else block the app crashes.
I don’t think the issue would be with MenuView passing in the array, because I have verified with the print statements that the value passed is correct, but I could have always missed something.
Further, I have tried directly passing in one of the quiz question arrays itself (avoiding the dependency on MenuView), and continue to run into the same problem.
struct ContentView: View {
@State private var isQuizViewShowing = false
// @State var contentQuizTitle = ""
@State var contentSelectedSet: [Question]?
@State var hasSelectedSet = false
var body: some View {
TabView {
MenuView(onQuizButtonTapped: { menuSelectedSet in
contentSelectedSet = menuSelectedSet
hasSelectedSet = true
print("The content set is (String(describing: contentSelectedSet))")
print("The selected set is (menuSelectedSet)")
isQuizViewShowing = true})
.tabItem {
Image(systemName: "book.fill")
Text("Learn")
}
PracticeView()
.tabItem {
Image(systemName: "chart.bar.fill")
Text("Practice")
}
SettingsView()
.tabItem {
Image(systemName: "gearshape.fill")
Text("Settings")
}
}
.fullScreenCover(isPresented: $isQuizViewShowing) {
if hasSelectedSet, let selectedSet = contentSelectedSet {
DebugQuizView(
isPresented: $isQuizViewShowing,
// quizTitle: contentQuizTitle,
selectedSet: selectedSet
)
}
else {
Text("Selected set is nil") // show a message if selectedSet is nil
}
}
}
}
Additionally if it helps, here is an example of the question that would be passed into ContentView from MenuView:
var questionsCore = [
Question(text: "What is the capital of New Zealand?", options: ["What if one of the answer choices is a longer answer", "Christchurch", "Wellington", "Auckland"], correctAnswer: "Wellington", imageName: nil, originalOptions: ["What if one of the answer choices is a longer answer", "Christchurch", "Wellington", "Auckland"]),
Question(text: "What is the highest mountain in New Zealand?", options: ["Mount Cook", "Mount Aspiring", "Mount Taranaki"], correctAnswer: "Mount Cook", imageName: UIImage(named: "cherry"), originalOptions: ["Mount Cook", "Mount Aspiring", "Mount Taranaki"]),
]
At first I thought it could have been an issue with the receiving view, but I made a new, empty one to check it and still receive the same issue there:
import SwiftUI
struct DebugQuizView: View {
@Binding var isPresented: Bool
@State var selectedSet: [Question]
var body: some View {
Text(selectedSet[1].text)
.foregroundColor(Color.green)
}
}
2
Answers
You could try this approach, using a
ObservableObject
model class to holdyour
contentSelectedSet
, as shown in the example code. Works for me.Why is using a simple
@State var contentSelectedSet: [Question]?
not working,I don’t know for sure, but @Paulw11 explanation seems to be correct.
It’s because you declared
contentSelectedSet
as@State
but didn’t use it anywhere inbody
. SwiftUI’s dependency tracking feature only calls forbody
when states are set if they are ones that have been previously read in body. You can fix it by forcing a read inbody
like this: