使用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?

查看:22
本文介绍了使用Firestore DB,当满足特定条件时,如何突破快照侦听器内部的for循环?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

一旦满足以下条件,我将尝试脱离此侦听器:如果myDay == self.daysOfWeek [self.picker.selectedRow(inComponent:0)] 满足,但我不满意得到我想要的结果.

I'm trying to break out of this listener once this condition if myDay == self.daysOfWeek[self.picker.selectedRow(inComponent: 0)] is met, but I'm not getting the results that I'm looking for.

一旦满足条件,它将继续遍历所有文档.我该如何正确编码?

Once the condition is met, it just continues to loop through all the documents. How do I code this up properly?

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()   
    }
}

推荐答案

问题中代码的第一个问题是Firestore是异步的.

The first issue with the code in the question is that Firestore is asynchronous.

闭包之后的任何代码都将在闭包中的代码之前执行.从服务器检索数据需要花费时间,并且检索到数据后,闭包中的代码将运行.

Any code following a closure will execute before the code in the closure. It takes time for data to be retrieved from the server and the code within the closure runs after that data is retrieved.

所以这行

if containsDay == true {

需要移动.

弗兰克的答案很好,但另一种解决方案是在转义时使用转义符

Frank's answer is excellent but another solution is to use escaping along with a break

假设我们要检索用户的uid-在这种情况下,我们遍历users节点以查找Bob.

Suppose we want to retrieve the uid of a user - in this case we iterate over the users node to look for Bob.

users
   uid_0
      name: "Frank"
   uid_1
      name: "Bill"
   uid_2
      name: "Bob"

这是我们调用函数的代码

Here's the code we call our function with

self.lookForBobsUid(completion: { bobsUid in
    print("Bob's uid is: \(bobsUid)")
})

然后读取所有用户的函数,对其进行迭代,然后当我们找到Bob时,返回Bobs uid并退出循环.

and then the function that reads in all of the users, iterates over them and then when we find Bob, return Bobs uid and break out of the loop.

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")
}

请注意,我在代码末尾添加了一行以演示异步调用的性质.

Note that I added a line at the end of the code to demonstrate the nature of asynchronous calls.

通常所说的所有这些,通常都可以避免遍历集合以寻找某些东西.

All of that being said, generally speaking, iterating over collections to look for something can usually be avoided.

看来您正在寻找解决办法

It appears you're looking for whatever this resolves to

self.daysOfWeek[self.picker.selectedRow(inComponent: 0)]

如果是这样,建议您查询self.colRef以获取该项目,而不是迭代查找它;这样会更快,并使用更少的资源,并且具有可伸缩性-如果要遍历100,000个节点,该怎么办!

If so, it would be advisable to query self.colRef for that item instead of iterating to find it; that will be way faster and use less resources and will also be scalable - what if there were 100,000 nodes to iterate over!

这篇关于使用Firestore DB,当满足特定条件时,如何突破快照侦听器内部的for循环?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆