我从SwiftUI视图中的switch语句中得到一些奇怪的行为。在这个视图中,当chosenParamsIndex第一次更新为初始化值以外的值(通过选择器进行选择)时,switch语句不会读取更新后的值。我已确认变量的值已正确更新。
如果chosenParamsIndex是通过在选择器外部选择测验选项(选项3-5)而首次更新的,则在单击第二个不同的选项之前,switch语句不会注册多次单击同一选项。
由于不一致的行为,我不确定这个问题的原因是什么。
struct PracticeView: View {
@State private var showingQuizView = false
@State var pickerChoice = 1
@State var chosenParamsIndex = 1
//Params: 0 = Practice 10, 1 = Practice 35, 2 = Practice 50, 3 = Mock, 4 = Difficult, 5 = Rapid Fire
var body: some View {
NavigationView {
ScrollView {
VStack(spacing: 20) {
// First rectangle with practice text
ZStack {
RoundedRectangle(cornerRadius: 25)
.frame(height: 200)
.foregroundColor(Color.blue)
VStack(spacing: 10) {
HStack(spacing: 10) {
Image(systemName: "chart.line.uptrend.xyaxis")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 45, height: 45)
VStack(alignment: .leading, spacing: 2) {
Text("Practice")
.font(.system(size: 24, weight: .bold))
Text("A selection of random questions.")
.font(.system(size: 16, weight: .semibold))
}
Spacer()
}
Picker(selection: $pickerChoice, label: Text("")) {
Text("10").tag(0)
Text("35").tag(1)
Text("50").tag(2)
}
.pickerStyle(SegmentedPickerStyle())
.onChange(of: pickerChoice) { newValue in
chosenParamsIndex = newValue
print("new picker value")
}
Button(action: {
showingQuizView = true
}) {
Text("Begin")
.font(.headline)
.foregroundColor(.white)
}
.frame(maxWidth: .infinity, minHeight: 40)
.background(Color.yellow)
.cornerRadius(10)
}
.padding()
}
// Second rectangle with timer, text, picker, and button
ZStack {
RoundedRectangle(cornerRadius: 25)
.frame(height: 150)
.foregroundColor(Color.blue)
VStack(spacing: 10) {
HStack(spacing: 10) {
Image(systemName: "stopwatch")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 45, height: 45)
VStack(alignment: .leading, spacing: 2) {
Text("Mock Test")
.font(.system(size: 24, weight: .bold))
Text("30 Minutes · 35 Questions")
.font(.system(size: 16, weight: .semibold))
}
Spacer()
}
Button(action: {
chosenParamsIndex = 3
showingQuizView = true
}) {
Text("Begin")
.font(.headline)
.foregroundColor(.white)
}
.frame(maxWidth: .infinity, minHeight: 40)
.background(Color.yellow)
.cornerRadius(10)
}
.padding()
}
// Third rectangle as a blank button
ZStack {
RoundedRectangle(cornerRadius: 25)
.frame(height: 150)
.foregroundColor(Color.blue)
VStack(spacing: 10) {
HStack(spacing: 10) {
Image(systemName: "exclamationmark.triangle")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 45, height: 45)
VStack(alignment: .leading, spacing: 2) {
Text("Difficult Questions")
.font(.system(size: 24, weight: .bold))
Text("Test your knowledge.")
.font(.system(size: 16, weight: .semibold))
}
Spacer()
}
Button(action: {
chosenParamsIndex = 4
showingQuizView = true
}) {
Text("Begin")
.font(.headline)
.foregroundColor(.white)
}
.frame(maxWidth: .infinity, minHeight: 40)
.background(Color.yellow)
.cornerRadius(10)
}
.padding()
}
//Fourth
ZStack {
RoundedRectangle(cornerRadius: 25)
.frame(height: 150)
.foregroundColor(Color.blue)
VStack(spacing: 10) {
HStack(spacing: 10) {
Image(systemName: "bolt")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 45, height: 45)
VStack(alignment: .leading, spacing: 2) {
Text("Rapid Fire")
.font(.system(size: 24, weight: .bold))
Text("3 Questions · 15 Seconds")
.font(.system(size: 16, weight: .semibold))
}
Spacer()
}
Button(action: {
chosenParamsIndex = 5
showingQuizView = true
}) {
Text("Begin")
.font(.headline)
.foregroundColor(.white)
}
.frame(maxWidth: .infinity, minHeight: 40)
.background(Color.yellow)
.cornerRadius(10)
}
.padding()
}
}
.padding()
.navigationTitle("Practice")
}
}
.fullScreenCover(isPresented: $showingQuizView) {
switch chosenParamsIndex {
case 0:
QuizView(isPresented: $showingQuizView, selectedSet: questionsRand10, isQuizTimed: false, setTimer: 0)
case 1:
QuizView(isPresented: $showingQuizView, selectedSet: questionsRand35, isQuizTimed: false, setTimer: 0)
case 2:
QuizView(isPresented: $showingQuizView, selectedSet: questionsRand50, isQuizTimed: false, setTimer: 0)
case 3:
QuizView(isPresented: $showingQuizView, selectedSet: questionsRand35, isQuizTimed: true, setTimer: 1800)
case 4:
QuizView(isPresented: $showingQuizView, selectedSet: questionsDifficult, isQuizTimed: false, setTimer: 0)
case 5:
QuizView(isPresented: $showingQuizView, selectedSet: questionsRapidFire, isQuizTimed: true, setTimer: 15)
default:
EmptyView()
}
}
}
}
2条答案
按热度按时间jogvjijk1#
因为
chosenParamsIndex
getter在body中的任何地方都没有被调用,这意味着SwiftUI的依赖跟踪不会检测到它--所以它不认为需要重新计算body,因此在设置chosenParamsIndex
时不会调用body。你可以像这样强迫它:FYI这个Swift语法被称为捕获列表。
顺便说一句,你的身体太大了,这将使它很难跟踪和解决这样的问题。尝试将其分解为仅需要它们在主体中使用的数据的小视图。
hlswsv352#
我设法重现了你的问题,我同意,这有点奇怪。我不能让它工作使用相同的状态变量,你正在使用。但是我找到了一个解决方案,使用了不同形式的
.fullScreenCover
和一个用于选择的枚举。当涉及switch语句时,使用枚举可能是一种更干净的方法: