我在从Firestore检索数据的代码中遇到问题。
我的代码中有2个类:锻炼和标记。 我的FirestoreDatabase中有2个集合:练习和标签
我需要从“锻炼”集合中获取所有“锻炼”文档。每个“练习”文档都有一个称为“标签”的字段,该字段是字符串数组。数组的每个字符串均包含“ id”,该id表示“ tag”在“ tags”集合上具有的文档。因此,在“标签”集合中查询此ID,使我能够获取正确的“标签”文档并访问其所有数据。这正是我要在代码中执行的操作。
我需要将所有练习合并到一个Exercise对象中,为此,我必须在另一个getDocument查询中使用getDocument查询,以便从“标签”集合中获取练习的“标签”
这是我的课程标记和练习:
class Tag {
var id: String?
var type: String?
var description: String?
init(id: String, type: String, description: String) {
self.id = id
self.type = type
self.description = description
}
}
class Exercise {
let id: String?
let group: String?
let tags: [Tag]
let title : String!
init(id: String, group: String, tags: [Tag], title: String){
self.id = id
self.group = group
self.tags = tags
self.title = title
}
}
这是我从Firestore数据库中获取“练习”的代码:
func fetchExercises(completion: @escaping ([Exercise]) -> ()) {
let exercisesRef = Firestore.firestore().collection("exercises")
exercisesRef.getDocuments() { (querySnapshot, err) in
var exercisesArray = [Exercise]()
if let err = err {
print("Error getting documents: \(err)")
} else {
for document in querySnapshot!.documents {
//print("\(document.documentID) => \(document.data())")
let myData = document.data()
let exercise_ID = document.documentID
let exercise_group = myData["Group"] as! String
let tagsArray = myData["Tags"] as! [String]
var exercise_tags: [Tag] = [Tag]()
for tag in tagsArray {
let tagID: String = tag
fetchTagfromID(tagID: tagID) { (tag: Tag) in
exercise_tags.append(tag)
}
}
let exercise_title = myData["Title"] as! String
exercisesArray.append(Exercise(id: exercise_ID,
group: exercise_group,
tags: exercise_tags,
title: exercise_title,
))
}
DispatchQueue.main.async{
print("EXERCISE FETCH HAS FINIS")
completion(exercisesArray)
}
}
}
}
func fetchTagfromID(tagID: String, completion: @escaping (Tag) -> ()) {
let tagRef = Firestore.firestore().collection("tags").document(tagID)
tagRef.getDocument() { (document, err) in
if let err = err {
print("Error getting documents: \(err)")
} else {
let myData = document?.data()
let tagDescription: String = myData!["description"] as! String
let tagType: String = myData!["type"] as! String
let tag: Tag = Tag(id: tagID, type: tagType, description:
tagDescription)
DispatchQueue.main.async{
print("TAGS FETCH HAS FINISHED")
completion(tag)
}
}
}
}
我的问题与执行时序(队列)代码有关。
我需要先填充“ exercise_tags”(第二个getDocument查询),然后继续并完成fetchExercise(主getDocument查询),但是Firestore不允许(或不知道如何)执行该操作。代码首先完成主要的getDocument查询(fetChExercises),然后返回完成次要的getDocument查询(fetchTagfromID)。
总而言之,我需要在运行时获取以下日志:
TAGS FETCH HAS FINISHED
EXERCISES FETCH HAS FINISHED
现在我正相反。
您知道家伙如何解决这个问题吗?也许正在更改调度队列...
我现在如何分两步解决问题,但是优雅的解决方案是一步完成所有事情。这是fetchExercises。
谢谢!
答案 0 :(得分:0)
因此,您需要做的是获取一个练习的所有标签,然后获取另一个练习。并最终获取调用完成处理程序以更新UI。我对代码进行了一些更改,您可以对其进行检查。
var exercisesArray = [Exercise]()
var listFromFetchExercise = []() //it will contain all object of array
querySnapshot!.documents. set DataType according to that.
var completion_exercises_Listner: () -> ()
func fetchExercises(completion: @escaping ([Exercise]) -> ()) {
let exercisesRef = Firestore.firestore().collection("exercises")
exercisesRef.getDocuments() { (querySnapshot, err) in
if let err = err {
print("Error getting documents: \(err)")
} else {
listFromFetchExercise = querySnapshot!.documents
fetchAllExercise()
DispatchQueue.main.async{
print("EXERCISE FETCH HAS FINIS")
completion(exercisesArray)
}
}
}
}
func fetchAllExercise(completion: @escaping ([Exercise]) -> ()){
fetchExercise()
completion_exercises_Listner = {
completion(exercisesArray);
}
}
func fetchExercise(index:Int = 0) {
let document = listFromFetchExercise[index]
let myData = document.data()
let exercise_ID = document.documentID
let exercise_group = myData["Group"] as! String
let tagsArray = myData["Tags"] as! [String]
var exercise_tags: [Tag] = [Tag]()
fetchTagsFromIDS(tagsArray) { (tag: [Tag]) in
exercise_tags.append(contentsOf: tag)
let exercise_title = myData["Title"] as! String
exercisesArray.append(Exercise(id: exercise_ID,
group: exercise_group,
tags: exercise_tags,
title: exercise_title,
DispatchQueue.main.async{
exercisesArray.append(tag)
if (index + 1) < exercisesArray.count {
fetchExercise(index+1,)
}else{
//Done
completion_exercises_Listner()
}
}
))
}
var listofTags = [String]()
var resultofTags = [Tag]()
func fetchTagsFromIDS(tagIDS:[String],completion: @escaping (_ tags:[
String]) -> ()){
listofTags = tagIDS;
fetchTagfromID() //Start With first tag
completionListner = {
completion(resultofTags);
}
}
var completionListner: () -> ()
func fetchTagfromID(index:Int = 0) {
let tagRef = Firestore.firestore().collection("tags").document(tagID)
tagRef.getDocument() { (document, err) in
if let err = err {
print("Error getting documents: \(err)")
} else {
let myData = document?.data()
let tagDescription: String = myData!["description"] as! String
let tagType: String = myData!["type"] as! String
let tag: Tag = Tag(id: tagID, type: tagType, description:
tagDescription)
DispatchQueue.main.async{
print("TAGS FETCH HAS FINISHED")
resultofTags.append(tag)
if (index + 1) < listofTags.count {
fetchTagfromID(index+1,)
}else{
//Done
completionListner()
}
//completion(tag)
}
}
} }