如何验证 firestore 中的文档路径?

how to validate document paths in firestore?

所以,在我之前的问题中,我最终弄清楚了我自己的问题(我建议在阅读这篇文章之前先看看那个),但是当我意识到该应用程序的所有用户的结果都相似,这是我不想要并且完全忘记的。

使用下面的功能,我可以购买活动,按钮会显示该活动,如果我取消,按钮就会消失,而且每个活动都是独一无二的,我很喜欢。现在,下面功能的问题是,如果我在 user1 帐户上进行购买并且按钮显示并保持原样,当我登录到 user2 帐户并且可能想购买相同的事件时,即使用户 2 未执行任何操作,按钮也已显示。

                getSchoolDocumentID { (schoolDocID) in
                if let schID = schoolDocID {
                    self.db.document("school_users/\(schID)/events/\(self.selectedEventID!)").getDocument { (documentSnapshot, error) in
                        if let error = error {
                            print("There was an error fetching the document: \(error)")
                        } else {

                            guard let docSnap = documentSnapshot!.get("purchased") else {
                                return
                            }
                            if docSnap as! Bool == true {
                                self.viewPurchaseButton.isHidden = false
                                self.cancelPurchaseButton.isHidden = false
                                self.creditCard.isHidden = true
                                self.purchaseTicketButton.isHidden = true

                            } else {
                                self.creditCard.isHidden = false
                                self.purchaseTicketButton.isHidden = false
                            }
                        }
                    }
                }
            }

所以我试图自己解决问题,但 运行 遇到了障碍。当用户购买事件并将详细信息存储在我稍后可以在查询中调用的字段中时,我尝试创建 events_bought 的子集合。这是我认为我可以用来使所有用户的购买独一无二的东西。

下面的函数查看 events_bought 子集合并拉出一个字段并将其与显示的 VC 上的一段数据匹配,问题是如果事件尚未购买,我继续那个用户,它崩溃了,并说文档参考路径如何有错误的段数,我没有得到,因为它与上面的函数相同,所以我意识到路径不存在并试图找出方法验证路径并提出下面的功能。

getEventsBoughtEventID { (eventBought) in
        if let idOfEventBought = eventBought {
            
            let docPath = self.db.document("student_users/\(self.user?.uid)/events_bought/\(idOfEventBought)")
            
            if docPath.path.isEmpty {
                self.creditCard.isHidden = false
                self.purchaseTicketButton.isHidden = false
            } else {
                self.db.document("student_users/\(self.user?.uid)/events_bought/\(idOfEventBought)").getDocument { (documentSnapshot, error) in
                    if let error = error {
                        print("There was an error trying to fetch this document: \(error)")
                    } else {
                        guard let docSnapEventName = documentSnapshot!.get("event_name") else {
                            return
                        }
                        
                        if docSnapEventName as! String == self.selectedEventName! {
                            self.viewPurchaseButton.isHidden = false
                            self.cancelPurchaseButton.isHidden = false
                            self.creditCard.isHidden = true
                            self.purchaseTicketButton.isHidden = true
                        }
                    }
                }
            }
        }
    }

我不确定它是否有效,所以我试试运气,但我仍然遇到相同的文档引用错误。如果有人能弄清楚我如何验证文档路径并使用逻辑来使某些事情发生,那就太好了。谢谢

在您的文档路径 "student_users/\(self.user?.uid)/events_bought/\(idOfEventBought)" 中,您使用 self.user?? 会产生 student_users/Optional(uid)/events_bought 字符串, 但不是 student_users/uid/events_bought 字符串。 使用 self.user!if let user = self.user {

所以我终于想出了如何做到这一点。这是一个 4 小时的磨合和挣扎,但我明白了,当然还有一些错误。所以我发现我的应用程序崩溃的原因不仅仅是因为路径段,而是因为某些事件 idOfEventBought 不存在,因为这些事件尚未购买并且没有名为 events_bought 的子集合尚未创建。

首先,当用户注册时,我在名为 events_bought 的子集合中添加了一个测试文档,这是有道理的,因为无论如何最终都必须制作它。

 db.document("student_users/\(result?.user.uid)/events_bought/test_document").setData(["test": "test"])

这行代码让我想出了下一个方法,可以验证事件是否被购买。

func checkIfUserMadePurchase(shouldBeginQuery: Bool) -> Bool {
    if shouldBeginQuery == true {
        
        getEventsBoughtEventID { (eventBought) in
            if let idOfEventBought = eventBought {

                self.docListener = self.db.document("student_users/\(self.user?.uid)/events_bought/\(idOfEventBought)").addSnapshotListener(includeMetadataChanges: true) { (documentSnapshot, error) in

                    if let documentSnapshot = documentSnapshot {

                        if documentSnapshot.exists {
                            self.creditCard.isHidden = true
                            self.purchaseTicketButton.isHidden = true
                            self.viewPurchaseButton.isHidden = false
                            self.cancelPurchaseButton.isHidden = false
                            
                        }
                    }
                }
            }
         
        }
        return true
    
 } else {
    creditCard.isHidden = false
    purchaseTicketButton.isHidden = false
    viewPurchaseButton.isHidden = true
    cancelPurchaseButton.isHidden = true
    return false
    }
}

我用这个方法来验证事件是否已经购买,以及它是否没有显示正确的按钮。

然后我在 UIAlertController 中的购买按钮被按下的过程中调用它。

       self.checkIfUserMadePurchase(shouldBeginQuery: true)

最后,我创建了一个函数,使用逻辑来验证事件是否已购买,如果已购买,则执行特定操作。然后我在 viewDidLoad()viewWillAppear()viewWillDisappear().

中调用这个函数
func purchasedStatusVerification() {
    db.collection("student_users/\(user?.uid)/events_bought").whereField("event_name", isEqualTo: self.selectedEventName!).getDocuments { (querySnapshot, error) in
        if let querySnapshot = querySnapshot {
            if querySnapshot.isEmpty {
                self.checkIfUserMadePurchase(shouldBeginQuery: false)
            } else {
                self.checkIfUserMadePurchase(shouldBeginQuery: true)
            }
        }
    }

}

所有这些都准备就绪后,我的应用程序可以按我想要的方式运行,我可以成功购买一个活动并且它不会显示在其他用户帐户中。有一些bug,比如创建新事件时,错误和正确的按钮都显示,但错误的按钮在登录和退出后消失了。此外,isHidden() 方法移动得非常慢,当我加载 vc 并且事件的状态为已购买时,purchaseTicketButton 会出现一瞬间,然后消失,这相当恼人的。总而言之,我想通了,并会在接近生产时间时尝试改进它。