You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift测验应用:QuestionView无法切换至下一题的问题

问题分析与解决方案

问题根源

  1. 数据未被观察:Quiz类是引用类型,但未遵循ObservableObject协议,修改progress和score时无法触发View刷新,导致界面感知不到进度变化。
  2. 题目参数未动态绑定:QuestionView通过初始化参数接收固定的question,没有和quiz.progress关联,即使进度更新,题目也不会自动切换。
  3. 状态更新无响应:点击答案修改quiz.progress后,因View未监听Quiz实例的变化,界面无法同步更新内容。

修复步骤

1. 修改Quiz模型,使其支持状态监听

让Quiz遵循ObservableObject,并将需要监听的属性标记为@Published:

import Combine

class Quiz: Identifiable, ObservableObject {
    let id = UUID()
    let name: String
    let illustration: String
    let difficulty: Difficulty
    let questions: [Question]
    
    @Published var score: Int
    @Published var progress: Int

    init(name: String, illustration: String, difficulty: Difficulty, questions: [Question], score: Int, progress: Int) {
        self.name = name
        self.illustration = illustration
        self.difficulty = difficulty
        self.questions = questions
        self.score = score
        self.progress = progress
    }
}

2. 重构QuestionView,动态绑定当前题目

移除固定的question参数,改为从quiz中动态获取当前题目,并通过@ObservedObject监听quiz的变化:

struct QuestionView: View {
    @ObservedObject var quiz: Quiz
    @State private var isFinished = false
    @State private var success = true
    
    // 动态计算当前题目
    private var currentQuestion: Question {
        quiz.questions[quiz.progress]
    }

    var body: some View {
        VStack(spacing: 40) {
            VStack {
                Text(quiz.name)
                    .font(.title3)
                    .bold()
                
                HStack(spacing: 20) {
                    ProgressBar(progress: 250 / CGFloat(quiz.questions.count) * CGFloat(quiz.progress))
                    Text("\(quiz.progress + 1)/\(quiz.questions.count)")
                        .bold()
                }
            }
            
            Text(currentQuestion.questionText)
                .font(.title)
                .fontWeight(.semibold)
                .frame(width: 300)
            
            Spacer()
            
            LazyVGrid(columns: [GridItem(.adaptive(minimum: 160, maximum: 240))], spacing: 10) {
                ForEach(currentQuestion.answers) { answer in
                    AnswerRow(answer: answer)
                        .onTapGesture {
                            if answer.isCorrect {
                                if success {
                                    quiz.score += 1
                                }
                                quiz.progress += 1
                                isFinished = true
                            } else {
                                success = false
                            }
                        }
                }
            }
            
            NavigationLink {
                // 检测是否完成所有题目,完成则跳转结果页
                if quiz.progress < quiz.questions.count {
                    QuestionView(quiz: quiz)
                } else {
                    Text("测验完成!得分:\(quiz.score)")
                    // 替换为你的结果页面,比如 ResultView(quiz: quiz)
                }
            } label: {
                PrimaryButton(text: "Continuer")
            }
            .disabled(!isFinished) // 启用禁用逻辑,防止未答题跳转

        }
        .padding(.vertical, 60)
        .navigationBarHidden(true)
    }
}

额外优化

  • 简化了答案点击的逻辑判断,代码更简洁;
  • 修正了ForEach中变量名的语义错误(从index改为answer);
  • 增加测验完成的判断,避免超出题目数组索引;
  • 启用NavigationLink的禁用状态,提升交互合理性。

内容的提问来源于stack exchange,提问作者Julien01

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 18:24:04