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

问题描述

所以,在我之前的问题中,我最终弄清楚了我自己的问题,(我建议在阅读这个之前先看看那个),但是当我意识到结果是,20 秒的荣耀被缩短了应用上的所有用户都相似,这是我不想要的并且完全忘记了。

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

                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 上的一条数据进行匹配,问题是如果尚未购买该事件,我继续与该用户进行,它崩溃并说文档引用路径如何有错误的段数,我没有得到,因为它与上面的函数相同,所以我意识到路径不存在并试图找出验证path 并想出了下面的函数

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

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

解决方法

所以我终于想出了如何做到这一点。这是一个 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 会在那里停留一瞬间,然后消失,这很烦人。总而言之,我想通了,并会在接近生产时间时尝试对其进行改进。

,

在您的文档路径 "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 {