第一次调用时捕获 Firebase 实时observeSingleEvent 数据失败

Posted

技术标签:

【中文标题】第一次调用时捕获 Firebase 实时observeSingleEvent 数据失败【英文标题】:Capturing Firebase realtime observeSingleEvent data fails on first call 【发布时间】:2020-04-03 19:46:33 【问题描述】:

我与 Firebase 实时数据库建立了有效连接。 observeSingleEvent 由点击的 IBAction 按钮触发。第一次调用获取数据失败。第二次按下按钮即可获取数据。第一次调用获取数据的方法是什么?我尝试多次调用observeSingleEvent,以编程方式点击按钮并添加等待以允许observeSingleEvent 完成。甚至在绝望时添加了完成块。任何提示我做错了什么都将受到高度赞赏。

--- 编辑 ---

按照@rob 的建议修复了下面的代码。除了 Rob 的答案之外,唯一的补充是在完成块的定义中需要 @escaping。现在效果很好。

var prodNo: String = "XXX000000"
var productDataLocal: [String: String] = ["ProdNo": "", "Location": ""]

@IBAction func findTapped(_ sender: Any) 
        fetchFirebaseData  () -> () in
            if productDataLocal["ProdNo"] == prodNo   // check that the data matches the product
                // launch a segue (that is detached from button)
                self.performSegue(withIdentifier: "moveToDetail", sender: nil)
            
            else 
                showError("Product \(prodNo) can't be found.")
            
        
   // findTapped

func fetchFirebaseData(completion: @escaping () -> ())   // --- EDIT ---@escaping addedd
    // check if this product can be found in Firebase!    
    self.ref.child("Id").child("\(prodNo)").observeSingleEvent(of: .value, with:
         (snapshot) in
            // try if this product can be found in Firebase
            let tempData = snapshot.value as? Dictionary<String, Any>
            if let actualData = tempData 
                self.copyData(actualData)
            
            completion()  // --- EDIT --- completion moved here
        )   (error) in
            print(error.localizedDescription)
            completion()  // --- EDIT ---and completion moved here
            
    // --- EDIT -- completion() removed from here
  // fetchFirebaseData

func copyData(_ actualData: Dictionary<String, Any>) 
    dump(actualData)  // for debugging what "actualData" actually contains
                      // this is always OK when execution gets here
    self.productDataLocal["ProdNo"] = actualData["ProdNo"] as? String
    self.productDataLocal["Location"] = actualData["Location"] as? String

“实际”数据的转储工作并产生正确的数据 - 当它被执行时。问题是我找不到任何方法来执行此代码,但第二次按下按钮。 (是的,“ProdNo”在 JSON 结构中重复,以便我可以检查它是否与请求的产品编号匹配。)--- 编辑 --- 上面的代码现在可以工作并且问题解决了

▿ 2 key/value pairs
  ▿ (2 elements)
    - key: "ProdNo"
    - value: XXX000000 #0
      - super: NSMutableString
        - super: NSString
          - super: NSObject
  ▿ (2 elements)
    - key: "Location"
    - value: "Warehouse 1" #1
      - super: NSMutableString
        - super: NSString
          - super: NSObject

【问题讨论】:

@rob- 谢谢。我会在早上(CET 时区)尝试下一件事。 【参考方案1】:

您正在同步调用您的完成块。在observeSingleEvent 完成之前,您不应该调用它。如果您将完成块移动到您的 observeSingleEvent 处理程序,您应该得到您正在寻找的结果:

func fetchFirebaseData(completion: @escaping () -> ())  // --- EDIT --- added "@escaping
    // check if this product can be found in Firebase!
    self.ref.child("Id").child("\(prodNo)").observeSingleEvent(of: .value, with:  (snapshot) in
            // try if this product can be found in Firebase
        let tempData = snapshot.value as? Dictionary<String, Any>
        if let actualData = tempData 
            self.copyData(actualData)
        
        completion()
        )  (error) in
            print(error.localizedDescription)
            completion()
        
  // fetchFirebaseData

【讨论】:

谢谢罗伯。我必须做的唯一补充是将完成定义为@escaping(大概是因为observeSingleEvent 正在转义)。原始代码现在已相应修复。我希望这会出现在 Firebase 文档或一些 YouTube 视频教程中。本来可以为我节省两天的工作时间 - 我几乎放弃了这个,经过所有不同的试验,我的代码现在变得一团糟......再次感谢!

以上是关于第一次调用时捕获 Firebase 实时observeSingleEvent 数据失败的主要内容,如果未能解决你的问题,请参考以下文章

使用协程的 Firebase 实时快照监听器

recyclerview行IGNORE重复

如何在 Firebase 实时数据库中存储浮点列表?

Firebase 实时数据库 setValue() 不工作

是否可以在 Vue 应用程序中呈现 Firebase 数据的实时变化?

FCM android onmessagereceived not called