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。
我正在开发这个小应用程序。我已将 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。