繁体   English   中英

使用 Firestore DB,当满足特定条件时,如何在快照侦听器内打破 for 循环?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM