array 似乎是空的,不能与 ForEach 循环一起使用

array seems to be empty and can not be used with ForEach loop

我正在开发这个小应用程序。我已将 AnswerRow 视图定义如下

struct AnswerRow: View {
    @EnvironmentObject var questionManager: QuestionManager
    @State private var isSelected = false
    var answer: Answer
    var green = Color(hue: 0.437, saturation: 0.711, brightness: 0.711)
    var red = Color(red: 0.71, green: 0.094, blue: 0.1)
    
    var body: some View {
        HStack(spacing: 20) {
            Image(systemName: "circle.fill")
                .foregroundColor(.accentColor)
                .font(.caption)
            
            Text(answer.text)
                .foregroundColor(.accentColor)
                .bold()
            
            if isSelected {
                Spacer()
                
                Image(systemName: answer.isCorrect ? "checkmark.circle.fill" : "x.circle.fill")
                    .foregroundColor(answer.isCorrect ? green : red)
            }
        }
        .padding()
        .frame(maxWidth: .infinity, alignment: .leading)
        .foregroundColor(questionManager.answerSelected ? (isSelected ? Color("AccentColor") : .gray) : Color("AccentColor"))
        .background(.white)
        .cornerRadius(10)
        .shadow(color: isSelected ? answer.isCorrect ? green : red : .gray, radius: 5, x: 0.5, y: 0.5)
        .onTapGesture {
            if !questionManager.answerSelected {
                isSelected = true
                questionManager.selectAnswer(answer: answer)

            }
        }
    }
}

在我的 QuestionView 中,我尝试用 ForEach 调用 AnswerRow,那里有可选代码来检查数组是否正常工作,这表明数组有 0 个成员,我不明白

>>QuestionView_swift

struct QuestionView: View {
    @EnvironmentObject var questionManager : QuestionManager
    var body: some View {
        VStack(alignment: .leading, spacing: 20) {
            
            Text("number of choices \(questionManager.answerChoices.count)") 
>>to check if the array is defined
            AnswerRow(answer: Answer(id: 1, text: "test Choice", isCorrect: true)) 
>> to check if the View is working without 'ForEach'
            
            ForEach(questionManager.answerChoices, id: \.id) { answer in
                AnswerRow(answer: answer)
                    .environmentObject(questionManager)
            }
        }
    }
}

我的模型如下,问题模型:

>>Question_swift

struct Question: Identifiable, Codable {
    var id: Int
    var question: String
    var correctAnswer : String
    var incorrectAnswers : [String]
    var type : String
    var imageName: String
    
    var answers: [Answer] {
        
            
            let correct = [Answer(id: id, text: correctAnswer, isCorrect: true)]
            let incorrects = incorrectAnswers.map { answer in
                Answer(id: id, text: answer, isCorrect: false)
            }
            let allAnswers = correct + incorrects
            
            return allAnswers.shuffled()
        
    }
}


    
    var questions: [Question] = load("questions.json")

    func load<T: Decodable>(_ filename: String) -> T {
        let data: Data

        guard let file = Bundle.main.url(forResource: filename, withExtension: nil)
            else {
                fatalError("Couldn't find \(filename) in main bundle.")
        }

        do {
            data = try Data(contentsOf: file)
        } catch {
            fatalError("Couldn't load \(filename) from main bundle:\n\(error)")
        }

        do {
            let decoder = JSONDecoder()
            return try decoder.decode(T.self, from: data)
        } catch {
            fatalError("Couldn't parse \(filename) as \(T.self):\n\(error)")
        }
    }

答案模型为

>> Answer_swift

struct Answer: Identifiable {
    var id : Int
    var text: String
    var isCorrect: Bool
}

我认为我的 QuestionManager 有一些问题,可能是数组失败的原因。

>>QuestionManager_swift

import Foundation
import SwiftUI
class QuestionManager : ObservableObject {
    @Published private(set) var questions : [Question] = []
    @Published private(set) var answerSelected = false
    @Published private(set) var reachedEnd = false
    @Published private(set) var score = 0
    @Published private(set) var progress: CGFloat = 0.00
    @Published private(set) var index = 0
    @Published private(set) var answerChoices: [Answer] = []
    @Published private(set) var question = ""
    @Published var markedQuestions : [Int] = []

    
    
    
    
    
    func selectAnswer(answer: Answer) {
        answerSelected = true
        
        if answer.isCorrect {
            score += 1
        } else {
            markedQuestions.append(index)
        }
    }
    
    func goToNextQuestion() {
        if index + 1 < questions.count {
            index += 1
            setQuestion()
        } else {
            reachedEnd = true
        }
    }
    
    func setQuestion() {
        answerSelected = false
        progress = CGFloat(Double((index + 1)) / Double(questions.count) * 350)

        
        if index < questions.count {
            let currentQuestion = questions[index]
            question = currentQuestion.question
            answerChoices = currentQuestion.answers
        }
    }
    
    
}

我是全新的,所以请用外行的术语帮助我。谢谢大家

您有 2 个不同的 [Question] 数组。

一个在你的视图模型中:

@Published private(set) var questions : [Question] = []

还有一个似乎是全局变量:

var questions: [Question] = load("questions.json")

只有全局变量会填充来自加载函数的数据。

删除全局函数,将加载函数移至您的 QuestionManager 并向其添加此初始化程序:

init(){
    questions = load("questions.json")
}

但您仍然需要填写您的问题,因此请将您的 QuestionView 更改为:

struct QuestionView: View {
    @EnvironmentObject var questionManager : QuestionManager
    var body: some View {
        VStack(alignment: .leading, spacing: 20) {
            
            Text("number of choices \(questionManager.answerChoices.count)")
            AnswerRow(answer: Answer(id: 1, text: "test Choice", isCorrect: true))
            
            ForEach(questionManager.answerChoices, id: \.id) { answer in
                AnswerRow(answer: answer)
                    .environmentObject(questionManager)
            }
        }.onAppear{
            questionManager.setQuestion() //Add this
        }
    }
}

编辑评论:

您没有看到所有答案,因为您为它们分配了相同的 ID。在您的 ForEach 中,您将此 ID 明确设置为视图的 ID。

你在调试区看到这个错误了吗?

ForEach<Array, Int, ModifiedContent<AnswerRow, _EnvironmentKeyWritingModifier<Optional>>>: the ID 1 occurs multiple times within the collection, this will give undefined results!

将您的模型更改为:

struct Answer: Identifiable {
    var id = UUID()
    var text: String
    var isCorrect: Bool
}

struct Question: Identifiable, Codable {
    var id: Int
    var question: String
    var correctAnswer : String
    var incorrectAnswers : [String]
    var type : String
    var imageName: String
    
    var answers: [Answer] {
        let correct = [Answer(text: correctAnswer, isCorrect: true)]
        let incorrects = incorrectAnswers.map { answer in
            Answer(text: answer, isCorrect: false)
        }
        let allAnswers = correct + incorrects
        
        return allAnswers.shuffled()
    }
}

answer 结构无论如何都不会保留,因此您每次都可以创建一个新 ID。