我有两个观察者,第二个观察者取决于第一个观察者的值。我似乎无法让第一个观察者工作,我在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()
}
任何帮助都将不胜感激。
self.bogus.string(forKey: "bogus"))"
为nil,因为 observeSingleEvent
是一种 async
方法,因此要获取所需的结果,您需要在第一个观察者内拨打第二个观察者,或者您可以使用完成处理程序
您可以这样使用完整的人:
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)
}
}
}
注意:您应该使用可选绑定来获取可选的值
由于您在第二个观察者的引用中使用了第一观察者的结果,因此在第一个观察者下方添加第二个观察者是一个非常糟糕的主意。而且添加延迟将不是一个可行的解决方案:这两个呼叫是异步的,这意味着您没有得到的原因很可能很可能是因为第二观察者甚至在第一个观察者返回任何数据之前就触发了。
这里的解决方案将使用完成处理程序,或者您可以将第二个观察者合并到第一个的完成块中,以确保始终尊重适当的订单(第一观察者 ->第二观察者)。
看起来像这样:
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.
}