[英]Can I use a Firestore snapshot listener to listen to changes only in cache?
[英]Using Firestore DB, how can I break out of a for loop inside of a snapshot listener when a certain condition is met?
if myDay == self.daysOfWeek[self.picker.selectedRow(inComponent: 0)]
满足这种情况,我会尝试打破这个监听器,但我没有得到我正在寻找的结果。
一旦满足条件,它就会继续循环遍历所有文档。 我该如何正确编码?
let addAction = UIAlertAction(title: "Add Workout", style: .default) { (UIAlertAction) in
if self.dayCount != 0 {
print("\(self.dayCount)")
self.colRef.addSnapshotListener { (querySnapshot, err) in
if let err = err
{
print("Error getting documents: \(err)");
}
else
{
for document in querySnapshot!.documents {
let myData = document.data()
let myDay = myData["dow"] as? String ?? ""
print(self.daysOfWeek[self.picker.selectedRow(inComponent: 0)])
print(myDay)
if myDay == self.daysOfWeek[self.picker.selectedRow(inComponent: 0)] {
containsDay = true
print(containsDay)
dayId = document.documentID
workoutColRef = Firestore.firestore().collection("/users/\(self.userIdRef)/Days/\(dayId)/Workouts/")
break //This Break needs to be somewhere else???
}
}
}
}
if containsDay == true {
//Create new workout and store within the selectedDay.
workoutColRef.addDocument(data: ["workout" : "\(self.textField2.text!)", "dayRef" : "\(dayId)"])
self.loadDays()
} else {
//Create new day as well as a new workout, and store the workout within the day.
let newDayRef = self.colRef.addDocument(data: ["dow" : "\(self.daysOfWeek[self.picker.selectedRow(inComponent: 0)])"])
Firestore.firestore().collection("/users/\(self.userIdRef)/Days/\(newDayRef.documentID)/Workouts/").addDocument(data: ["workout" : "\(self.textField2.text!)", "dayRef" : newDayRef])
newDayRef.getDocument { (docSnapshot, err) in
if let err = err
{
print("Error getting documents: \(err)");
}
else
{
let myData = docSnapshot!.data()
let myDay = myData!["dow"] as? String ?? ""
self.daysArray.append(myDay)
}
}
self.dayIdArray.append(newDayRef.documentID)
self.loadDays()
}
} else {
self.dayCount += 1 //If there are no days/workouts, we create new day as well as a new workout, and store the workout within the day.
let newDayRef = self.colRef.addDocument(data: ["dow" : "\(self.daysOfWeek[self.picker.selectedRow(inComponent: 0)])"])
Firestore.firestore().collection("/users/\(self.userIdRef)/Days/\(newDayRef.documentID)/Workouts/").addDocument(data: ["workout" : "\(self.textField2.text!)", "dayRef" : newDayRef])
newDayRef.getDocument { (docSnapshot, err) in
if let err = err
{
print("Error getting documents: \(err)");
}
else
{
let myData = docSnapshot!.data()
let myDay = myData!["dow"] as? String ?? ""
self.daysArray.append(myDay)
}
}
self.dayIdArray.append(newDayRef.documentID)
self.loadDays()
}
}
一种简单的方法是保留一个标志变量,指示您是否找到了文档:
let foundIt = false
for document in querySnapshot!.documents {
if !foundIt {
let myData = document.data()
let myDay = myData["dow"] as? String ?? ""
if myDay == self.daysOfWeek[self.picker.selectedRow(inComponent: 0)] {
containsDay = true
dayId = document.documentID
workoutColRef = Firestore.firestore().collection("/users/\(self.userIdRef)/Days/\(dayId)/Workouts/")
foundIt = true
}
}
}
问题中代码的第一个问题是 Firestore 是异步的。
闭包之后的任何代码都将在闭包中的代码之前执行。 从服务器检索数据需要时间,并且闭包中的代码在检索到数据后运行。
所以这条线
if containsDay == true {
需要移动。
弗兰克的回答非常好,但另一种解决方案是使用 escaping 和休息
假设我们想要检索用户的 uid - 在这种情况下,我们遍历用户节点以查找 Bob。
users
uid_0
name: "Frank"
uid_1
name: "Bill"
uid_2
name: "Bob"
这是我们称之为 function 的代码
self.lookForBobsUid(completion: { bobsUid in
print("Bob's uid is: \(bobsUid)")
})
然后是 function 读取所有用户,对其进行迭代,然后当我们找到 Bob 时,返回 Bobs uid 并跳出循环。
func lookForBobsUid(completion: @escaping ( (String) -> Void ) ) {
let usersCollection = self.db.collection("users")
usersCollection.getDocuments(completion: { snapshot, error in
if let err = error {
print(err.localizedDescription)
return
}
guard let documents = snapshot?.documents else { return }
for doc in documents {
let uid = doc.documentID
let name = doc.get("name") as? String ?? "No Name"
print("checking name: \(name)")
if name == "Bob" {
print(" found Bob, leaving loop")
completion(uid)
break
}
}
})
print("note this line will print before any users are iterated over")
}
请注意,我在代码末尾添加了一行来演示异步调用的性质。
综上所述,一般来说,通常可以避免遍历 collections 来寻找某些东西。
看来您正在寻找任何解决方法
self.daysOfWeek[self.picker.selectedRow(inComponent: 0)]
如果是这样,建议为该项目查询 self.colRef 而不是迭代查找它; 这将更快,使用更少的资源,并且还具有可扩展性 - 如果有 100,000 个节点可以迭代!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.