我正在尝试查询数据并将其更新到Firebase。但是我无法获取数据。似乎程序没有遇到ref.observeSingleEvent 我该怎么做才能解决此问题?
func getId(path:String, value:String?, completion: @escaping (String?) -> Void) {
let ref = Database.database().reference(withPath: path).queryOrdered(byChild: "name").queryEqual(toValue: value)
ref.observeSingleEvent(of: .childAdded, with: { snapshot in
print("running in getId")
completion(snapshot.key)
}) { (error) in
print(error.localizedDescription)
}
}
@objc func onTapConfirmed(){
self.getId(path: "patients", value: self.kardex?.patient?.name) { snapshotKey in
BookingViewController.kardexDict["patient"] = snapshotKey as AnyObject?
print("1:get patient name")
}
self.getId(path: "nurses", value: BookingTreatmentListController.nurseName) { snapshotKey in
BookingViewController.kardexDict["nurse"] = snapshotKey as AnyObject?
print("2:get nurse name")
}
Database.database().reference().child("kardexes").child(BookingViewController.newKardex.id).updateChildValues(BookingViewController.kardexDict)
print("save kardexDict")
}
我希望得到以下结果
“ 1:获取患者姓名”->“在getId中运行”-> “ 2:获取护士姓名”->“在getId中运行”->“保存kardexDict”
但是我知道了
“ 1:获取患者姓名”->“ 2:获取护士姓名”->“保存kardexDict”
并且kardexDict中的数据不正确,因为该数据不是从函数getId()获得的 我该怎么做才能迫使程序按照我的预期进行。
答案 0 :(得分:0)
您使用Firebase的方式错误:
observeSingleEvent
异步运行,因此事件的顺序为:“在getId中运行”->“ 1:获取患者姓名” updateChildValues
通常会在任何observeSingleEvent
完成之前被调用因此,在获得患者或护士姓名之前,您首先将空(?)kardexDict
写到firebase。
此外,请注意completion
闭包未在主线程中运行。因此,您可能会观察到一些不可预测的并发问题/竞争条件。
您要做的就是等待所有observeSingleEvent
完成,然后将数据写回。
因此,您的想法 或多或少会像这样(可能不完全编译,因为我没有运行您的环境):
func getId(path:String, value:String?, completion: @escaping (String?) -> Void) {
let ref = Database.database().reference(withPath: path).queryOrdered(byChild: "name").queryEqual(toValue: value)
ref.observeSingleEvent(of: .childAdded, with: { snapshot in
print("running in getId")
completion(snapshot.key)
}) { (error) in
print(error.localizedDescription)
}
}
@objc func onTapConfirmed(){
let patientName = self.kardex?.patient?.name
let nurseName = BookingTreatmentListController.nurseName
self.getId(path: "patients", value: patientName) { snapshotKey in
print("1:got patient")
let patient = snapshotKey as AnyObject?
self.getId(path: "nurses", value: nurseName) { snapshotKey in
print("2:got nurse")
let nurse = snapshotKey as AnyObject?
DispatchQueue.Main.async {
print("save kardexDict (in main thread!")
BookingViewController.kardexDict["patient"] = patient
BookingViewController.kardexDict["nurses"] = nurse
let kardexes = Database.database().reference().child("kardexes")
kardexes.child(BookingViewController.newKardex.id).updateChildValues(BookingViewController.kardexDict)
}
}
}
}
尽管如此,可能效率不高,因为涉及两个单独的网络呼叫(首先是患者,然后是护士)。也许您最好使用observe
而不是observeSingleEvent
。