【问题标题】:Firebase one of two observers not workingFirebase 两个观察者之一不工作
【发布时间】:2017-09-22 02:40:41
【问题描述】:

我有两个观察者,第二个观察者依赖于第一个观察者的值。我似乎无法让第一个观察者工作,我在 Xcode 上没有收到任何错误。第一个功能必须检查用户配置文件中的信息,然后使用该信息在数据库中搜索不同的信息。这是我的代码:

func loadposts() {
    ref = Database.database().reference()
    let trace = Performance.startTrace(name: "test trace")
    trace?.incrementCounter(named:"retry")
    let userID = Auth.auth().currentUser?.uid
    print(userID!)


   ref.child("Users").child(userID!).observeSingleEvent(of: .value, with: { (snapshot) in
        // Get user value
        let value = snapshot.value as? NSDictionary
        let one1 = value?["Coupon Book"] as? String ?? ""
        print("one1: \(one1)")
        self.bogus.set(one1, forKey: "bogus")
    }) { (error) in
        print(error.localizedDescription)
    }

    delay(0.1) {
    print("bogus: \(self.bogus.string(forKey: "bogus"))")
    Database.database().reference().child("Coupons").child(self.bogus.string(forKey: "bogus")!).observe(.childAdded) { (Snapshot : DataSnapshot) in
        if let dict = Snapshot.value as? [String: Any] {
            let captiontext = dict["company name"] as! String
            let offerx = dict["offer count"] as! String
            let logocomp = dict["logo"] as! String
            let actchild = dict["childx"] as! String
            let post = Post(captiontext: captiontext, PhotUrlString: actchild, offertext: offerx, actualphoto: logocomp)
            self.posts.append(post)
            self.tableview.reloadData()

            print(self.posts)
        }
    }
    }
    trace?.stop()
}

感谢任何帮助。

【问题讨论】:

  • 此语句是否打印任何内容print("bogus: \(self.bogus.string(forKey: "bogus"))")
  • @3stud1ant3 不,它是 nil
  • 它是 nil 因为observeSingleEvent 是一个async 方法,所以要获得所需的结果,您需要在第一个观察者中调用第二个观察者,或者您可以使用完成处理程序

标签: swift firebase firebase-realtime-database


【解决方案1】:

self.bogus.string(forKey: "bogus"))" 是 nil,因为 observeSingleEvent 是一个 async 方法,因此要获得所需的结果,您需要在第一个观察者中调用第二个观察者,或者您可以使用完成处理程序

你可以像这样使用completionHandler:

guard let uid = Auth.auth().currentUser?.uid else {
    return
  }

    func firstObserverMethod(completionCallback: @escaping () -> Void) {

                ref.child("Users").child(uid).observeSingleEvent(of: .value, with: { (snapshot) in
                    // Get user value
                    if let value = snapshot.value as? [String: Any] {
                          let one1 = value["Coupon Book"] as? String

                          print("one1: \(one1)")
                          self.bogus.set(one1, forKey: "bogus")
                          completionCallback()

                    }




                }) { (error) in
                    print(error.localizedDescription)
                }
            }

现在使用上面的方法:

    firstObserverMethod {

                     print("bogus: \(self.bogus.string(forKey: "bogus"))")
                     guard let bogusString = self.bogus.string(forKey: "bogus") else {                
                            print("bogus is not set properly")
                            return
                     } 


 Database.database().reference().child("Coupons").child(bogusString).observe(.childAdded) { (Snapshot : DataSnapshot) in
                        if let dict = Snapshot.value as? [String: Any] {
                            let captiontext = dict["company name"] ?? ""
                            let offerx = dict["offer count"] ?? ""
                            let logocomp = dict["logo"] ?? ""
                            let actchild = dict["childx"] ?? ""
                            let post = Post(captiontext: captiontext, PhotUrlString: actchild, offertext: offerx, actualphoto: logocomp)
                            self.posts.append(post)
                            DispatchQueue.main.async {
                                   self.tableview.reloadData()
                            }


                            print(self.posts)
                        }
                    }

                }

注意:您应该使用可选绑定从可选中获取值

【讨论】:

  • one1: Broward1718 bogus: Optional("Broward1718") 致命错误:在展开可选值时意外发现 nil -------------------- ----------------- 致命错误:在展开可选值时意外发现 nil
  • @voodoo Broward1718 代表什么?在您的数据库中
  • Broward1718 是一个有子孩子的孩子
  • 我的错,我在数据库中丢失了一个值。感谢您的帮助。
  • @downvoter 请告诉我问题,以便我改进答案,谢谢
【解决方案2】:

由于您在第二个观察者的引用中使用了第一个观察者的结果,因此将第二个观察者添加到第一个观察者的正下方是一个非常糟糕的主意。并且添加延迟不是一个可行的解决方案:这两个调用是异步的,这意味着您没有得到的原因很可能是因为第二个观察者在第一个观察者返回任何数据之前就被触发了。

这里的解决方案是使用完成处理程序,或者您可以将第二个观察者合并到第一个的完成块中,以确保始终遵守正确的顺序(第一个观察者 -> 第二个观察者) .

它看起来像这样:

func loadposts() {

    // ...

    // 1st Observer here

    ref.child("Users").child(userID!).observeSingleEvent(of: .value, with: { (snapshot) in

       // Get your value here

       guard let one1 = snapshot.childSnapshot(forPath: "Coupon Book").value as? String else { return }

       // 2nd Observer here. Now you can use one1 safely:

       Database.database().reference().child("Coupons").child(one1).observe(.childAdded) { (Snapshot : DataSnapshot) in

            // ...

        }

    })

}

现在,您还可以在代码中改进几件事,但与问题没有直接关系:

我建议您使用保护语句而不是强制展开,这可能最终导致您的应用程序在某些时候崩溃。

例如,您可以像这样检查当前用户是否存在:

guard let currentUserID = Auth.auth().currentUser?.uid else {
    return
}

// Now you can use safely currentUserID

此外,当您尝试从快照中获取数据时,使用强制转换也不是一个好主意。你最好这样写:

   yourRef.observeSingleEvent(of: .value, with: { (snapshot) in

         for child in snapshot.children.allObjects as! [DataSnapshot] {

         guard let text = child.childSnapshot(forPath: "text").value as? String, let somethingElse =  child.childSnapshot(forPath: "otherValue").value as? NSNumber else {
             return
         }

         // And so on, depending of course on what you have in your database.

  }

【讨论】:

    猜你喜欢
    • 2014-03-24
    • 2021-10-24
    • 2011-04-14
    • 2013-01-30
    • 2017-12-04
    • 1970-01-01
    • 2015-02-14
    • 2015-09-05
    • 1970-01-01
    相关资源
    最近更新 更多