Swift中从Firestore获取含Map的数组值问题求助
问题:无法从Firebase Firestore获取
midTerm、finalTerm和lectureGradeId字段值 我正在为学校项目开发一款App,目前遇到了无法解决的问题:尝试从Firebase Cloud Firestore中获取midTerm、finalTerm和lectureGradeId的值,但除了这些值之外,能成功获取Firestore中的所有其他数据。
相关代码
Students.swift
import Foundation import FirebaseFirestore struct Grades: Codable, Hashable { var lectureGradeId: String var midTerm: String var endTerm: String } struct Students: Identifiable, Codable { var id: String var email: String var studentName: String var studentSurname: String var studentTerm: String var studentBirthday: String var studentClass: Int var studentDept: String var studentFaculty: String var studentIsActive: Bool var studentIsGraduated: Bool var studentLectures: [String]? var studentGrades: [Grades]? }
StudentsViewModel.swift
import Foundation import Firebase class StudentsViewModel: ObservableObject { @Published var students = [Students]() private var db = Firestore.firestore() func fetchData() { db.collection("Students").whereField("id", isEqualTo: "20704029").addSnapshotListener { querySnapshot, error in guard let documents = querySnapshot?.documents else { print("No documents") return } self.students = documents.map { (queryDocumentSnapshot) -> Students in let data = queryDocumentSnapshot.data() let id = data["id"] as? String ?? "" let email = data["email"] as? String ?? "" let studentName = data["studentName"] as? String ?? "" let studentSurname = data["studentSurname"] as? String ?? "" let studentTerm = data["studentTerm"] as? String ?? "" let studentBirthday = data["studentBirthday"] as? String ?? "" let studentClass = data["studentClass"] as? Int ?? 0 let studentDept = data["studentDept"] as? String ?? "" let studentFaculty = data["studentFaculty"] as? String ?? "" let studentIsActive = data["studentIsActive"] as? Bool ?? true let studentIsGraduated = data["studentIsGraduated"] as? Bool ?? false let studentLectures = data["studentLectures"] as? Array ?? [""] let student = Students(id: id, email: email, studentName: studentName, studentSurname: studentSurname, studentTerm: studentTerm, studentBirthday: studentBirthday, studentClass: studentClass, studentDept: studentDept, studentFaculty: studentFaculty, studentIsActive: studentIsActive, studentIsGraduated: studentIsGraduated, studentLectures: studentLectures) //print(student) return student } } } }
GradesPage.swift
import SwiftUI struct GradesPage: View { @ObservedObject private var viewModel = StudentsViewModel() var body: some View { NavigationView { List(viewModel.students) { student in VStack(alignment: .leading) { Text("Student Name: ") + Text(" ") + Text(student.studentName) + Text(" ") + Text(student.studentSurname) //I want to add the grades to see in here but don't know how to handle it } } }.onAppear { self.viewModel.fetchData() } } }
Firestore结构

已尝试的解决方案
- 参考Firestore Codable相关指南
- 查阅Firestore官方文档
解决方案
1. 修正字段名不匹配问题
Firestore中的成绩字段是finalTerm,但你定义的Grades结构体里写的是endTerm,字段名不匹配会导致解析失败。修改结构体:
struct Grades: Codable, Hashable { var lectureGradeId: String var midTerm: String var finalTerm: String // 改为和Firestore一致的字段名 }
2. 改用Codable自动解析(替代手动赋值)
手动解析容易遗漏字段(比如你没处理studentGrades),用Firestore自带的Codable支持更可靠,修改fetchData方法:
func fetchData() { db.collection("Students").whereField("id", isEqualTo: "20704029").addSnapshotListener { querySnapshot, error in guard let documents = querySnapshot?.documents else { print("No documents") return } self.students = documents.compactMap { document in do { // 直接将文档解码为Students对象 let student = try document.data(as: Students.self) return student } catch { print("解码失败:\(error)") return nil } } } }
3. 在页面中展示成绩数据
现在student.studentGrades已能正确获取,修改GradesPage的视图代码:
VStack(alignment: .leading) { Text("Student Name: ") + Text(" ") + Text(student.studentName) + Text(" ") + Text(student.studentSurname) // 遍历展示成绩 if let grades = student.studentGrades { ForEach(grades, id: \.lectureGradeId) { grade in VStack(alignment: .leading, spacing: 4) { Text("课程ID:\(grade.lectureGradeId)") Text("期中成绩:\(grade.midTerm)") Text("期末成绩:\(grade.finalTerm)") } .padding(.vertical, 8) .border(.gray, width: 0.5) .padding(.vertical, 4) } } }
内容的提问来源于stack exchange,提问作者caneraltuner
相关产品推荐
相关产品推荐

