使用 Swift 在 firestore 中引入包含地图的数组值

问题描述 投票:0回答:1

我正在为我的学校项目开发一个应用程序,但遇到了一个问题,我无法处理它。我正在尝试从我的 Firebase Cloud Firestore 获取

midTerm
finalTerm
lectureGradeId
值。除了这些值之外,我可以从 Firestore 获取所有值。

为了清楚起见,我将代码和 Firestore 结构放在下面:

学生.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 Structure

我尝试过的解决方案:

Peter Friese 文档

Firestore 官方文档

提前致谢,欢迎所有帮助!

swift firebase google-cloud-firestore swiftui
1个回答
0
投票

注意,您应该使用

@StateObject private var viewModel = StudentsViewModel()
。 另请注意,您的代码中没有
finalTerm
并且
NavigationView
已弃用,请使用
NavigationStack

要在

studentGrades
视图中显示
GradesPage
, 只需使用
ForEach
,例如:

struct GradesPage: View {
    @StateObject private var viewModel = StudentsViewModel()
    
    var body: some View {
        NavigationStack {  // <--- here
            List(viewModel.students) { student in
                VStack(alignment: .leading) {
                    Text("Student Name: ") + Text(" ") + Text(student.studentName) + Text(" ") + Text(student.studentSurname)

                    ForEach(student.studentGrades ?? []) { grade in  // <--- here
                       Text(grade.lectureGradeId)
                       Text(grade.midTerm)
                       Text(grade.endTerm)
                    }
                }
            }
        }
        .onAppear {
            self.viewModel.fetchData()
        }
    }
}

struct Grades: Identifiable, Codable, Hashable {  //<--- here
    let id = UUID()
    var lectureGradeId: String
    var midTerm: String
    var endTerm: String
    
    enum CodingKeys: String, CodingKey {
        case lectureGradeId, midTerm, endTerm
    }
}

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]?
}
© www.soinside.com 2019 - 2024. All rights reserved.