问题描述
对于集合“school_users”中的每个文档,我都有一个名为 events 的子集合。
当学校用户创建事件时,它会使用 school_id
字段创建并放入该子集合中。我想要做的是在学生用户的表视图控制器中显示由学校创建的具有相同 ID 的事件(学生用户的学生 ID 与学校 ID 匹配)。
我不知道该怎么做,所以我尝试了一些方法。
func getStudentID(completion: @escaping ((String?) -> ())) {
db.collection("student_users").whereField("userID",isEqualTo: user!.uid).getDocuments { (querySnapshot,err) in
if let err = err {
print("There was an error fetching the documents: \(err)")
} else {
self.studID = querySnapshot!.documents.map { document in
return StudentID(studentID: (document.get("school_id") as! String))
}
let fixedID = "\(self.studID)"
let substring = fixedID.dropFirst(30).dropLast(3)
let realString = String(substring)
completion(realString)
}
}
}
我根据我从上次尝试将学生 ID 作为字符串获取的问题中学到的知识创建了一个函数。
但在此之前,我在没有完成处理程序的情况下使用上述相同的函数并返回一个字符串并尝试将其输入到查询中。显然它行不通,但我还是尝试了。
//MARK: - Needs to be fixed
func getSchoolID() {
db.collectionGroup("events").whereField("school_id",isEqualTo: getStudentID()).getDocuments { (querySnapshot,error) in
if let error = error {
print("There was an error fetching the events: \(error)")
} else {
self.events = querySnapshot!.documents.map { document in
return EventName(eventName: (document.get("event_name") as? String) ?? "")
}
self.tableView.reloadData()
}
}
}
所以我尝试的最后一件事是在 cellForRowAt
tableview 方法中调用完成处理程序。
override func tableView(_ tableView: UITableView,cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: Constants.CellDetails.cellName,for: indexPath)
getStudentID { [weak self] (realString) in
cell.textLabel?.text = self?.events[indexPath.row].eventName
}
cell.textLabel?.font = UIFont(name: Constants.CellDetails.fontName,size: 22)
return cell
}
这些最终都不起作用,我只是有一堆错误。回顾一下,基本上我想要做的是用来自学校的事件名称填充 Student TableVC 中的单元格,这些事件名称与它们具有匹配的 ID。将添加一些额外的照片以进行更多说明。
所以这些是由 Santa Fe High School 管理员用户创建的事件,我希望它们显示在 Santa Fe Highschool 学生用户的 tableview 中。
如果学校 ID 匹配,这是我希望他们出现的 VC。登录的用户确实具有与 Santa Fe High 相同的 ID,所以我希望它们显示出来,但这就是我无法弄清楚的。希望你明白我在做什么。欢迎提出更多问题。
解决方法
这适用于任何遇到相同问题的人
所以基本上我所做的是将整个查询放入完成处理程序中。
这是它的开始。
func getStudentID(completion: @escaping ((String?) -> ())) {
db.collection("student_users").whereField("userID",isEqualTo: user!.uid).getDocuments { (querySnapshot,err) in
if let err = err {
print("There was an error fetching the documents: \(err)")
} else {
self.studID = querySnapshot!.documents.map { document in
return StudentID(studentID: (document.get("school_id") as! String))
}
let fixedID = "\(self.studID)"
let substring = fixedID.dropFirst(30).dropLast(3)
let realString = String(substring)
completion(realString)
}
}
}
这里的这个函数以我需要的字符串格式获取studentID,以便我可以将其放入查询中。
如你所见,它是一个完成处理函数。我知道我需要那个确切的值,并且知道我不能只在查询调用的 isEqualTo:
参数中完成它,所以我决定通过在 viewDidLoad()
中抛出一个打印语句来测试该函数.我很高兴看到它出现在控制台上。所以我意识到为什么不做同样的事情:
getStudentID { (studentID) in
if let id = studentID {
print(id)
}
}
而是将 id
常量设为查询调用的 isEqualTo:
参数中的值。
这导致我这样做...
func getSchoolID() -> String {
getStudentID { (studentID) in
if let idForStudent = studentID {
self.db.collectionGroup("events").whereField("school_id",isEqualTo: idForStudent).getDocuments { (querySnapshot,error) in
if let error = error {
print("There was an error fetching the events: \(error)")
} else {
self.events = querySnapshot!.documents.map { document in
return EventName(eventName: (document.get("event_name") as? String) ?? "")
}
self.tableView.reloadData()
}
}
}
}
return "\(events)"
}
这最终完美地工作,我记得我对自己重复了无数次,天哪。这是我最喜欢的编码部分,解决了这个大问题。
最后,为了填充单元格,我只需要编写这行代码
cell.textLabel?.text = events[indexPath.row].eventName
而且它工作得很好。这是我的解决方案,我感到无比自豪。