我有一个代码,通常应该从Firebase向我返回一个值。
我的Firebase结构是:
Experience{
UserId{
LDG_DAY: "4"
LDG_NIGHT: "0"
APCH_IFR: "0"
}
}
我的代码是:
func getUserExp(){
let ref = Database.database().reference()
let userID = Auth.auth().currentUser?.uid
let Date = self.flightDate.text
ref.child("Experience")/*.child(userID!)*/.observeSingleEvent(of: .value) {(snapshot) in
if snapshot.hasChild(userID!){
let value = snapshot.value as? NSDictionary
let ldg_day = value?["LDG_DAY"] as? String ?? "123"
let ldg_night = value?["LDG_NIGHT"] as? String ?? "0"
let apch_ifr = value?["APCH_IFR"] as? String ?? "0"
self.intLdgDay = Int(ldg_day)!
self.intLdgNight = Int(ldg_night)!
self.intApchIfr = Int(apch_ifr)!
print("string = \(ldg_day) int = \(self.intLdgDay)")
}
}
}
现在代码无法按照我的意愿运行...实际上,我的代码返回了基本的as? String ?? "123"
值,但是snapshot.value从firebase中获得了很好的价值...
怎么了 ?我将此代码用于应用程序的许多其他部分,对此没有问题吗?
感谢您的帮助
答案 0 :(得分:1)
我相信您想在尝试读取子数据之前确保该节点存在。
注意:
我看到读取路径已注释掉uid,因此尚不清楚您是打算读取一个用户(保留uid)还是要一次加载每个用户(数千个)。该答案假定您仅打算阅读该特定用户节点。如果您打算一次读取所有用户节点,请参阅@Callam答案。
您现在使用的代码正在使用snapshot.hasChild,该文件在节点内查找以查看子代,用户uid是否存在,并且不存在,因此代码将始终失败。
if snapshot.hasChild(userID!)
我认为您想要做的是使用snapshot.exists来确保它是有效的节点,然后再进行读取。这是代码:
let experienceRef = self.ref.child("Experience")
let usersExpRef = experienceRef.child(uid)
usersExpRef.observeSingleEvent(of: .value) { snapshot in
if snapshot.exists() {
let value = snapshot.value as! [String: Any]
let ldg_day = value["LDG_DAY"] as? String ?? "123"
print("string = \(ldg_day)")
} else {
print("the \(uid) node does not exist")
}
}
我还建议在尝试使用它们之前安全地解开选项,因为它们可能为零,这会使您的代码崩溃。
guard let thisUser = Auth.auth().currentUser else { return }
let uid = thisUser.uid
请注意,我还用它的Swifty副本[String:Any]替换了旧的objc NSDictionary
答案 1 :(得分:0)
假设您的结构是从根开始的,并且Experience
包含多个用户ID,则由于/*.child(userID!)*/
已被注释掉,因此您的代码当前正在观察所有用户ID的值。
因此,您正在请求每个用户的体验,并在客户端上检查当前用户是否以孩子的身份存在–如果当前用户的ID位于Experience/$uid
,则将成功。
ref.child("Experience")/*.child(userID!)*/.observeSingleEvent(of: .value) { (snapshot) in
if snapshot.hasChild(userID!) {
let value = snapshot.value as? NSDictionary
现在我们有了一个包含所有“体验”的快照,并且我们已经确认它具有当前用户ID的子代-我们需要获取那个子代并将其值转换为字典
let value = snapshot.childSnapshot(forPath: userID).value as? NSDictionary
这可以解决问题,但显然,我们不想在单个用户的设备上下载所有体验,而且他们甚至都不应该具有请求该参考位置的权限。
因此,如果您取消注释.child(userID!)
,快照将只是一个体验,因此snapshot.hasChild(userID!)
将失败。相反,您可以使用snapshot.exists()
和/或条件转换来确定userID
的快照是否存在和/或可转换。
func getUserExp() {
let ref = Database.database().reference()
let userID = Auth.auth().currentUser?.uid
let Date = self.flightDate.text
ref.child("Experience").child(userID!).observeSingleEvent(of: .value) { snapshot in
if snapshot.exists() {
let value = snapshot.value as? [String:String]
let ldg_day = value?["LDG_DAY"] ?? "123"
let ldg_night = value?["LDG_NIGHT"] ?? "0"
let apch_ifr = value?["APCH_IFR"] ?? "0"
self?.intLdgDay = Int(ldg_day)!
self?.intLdgNight = Int(ldg_night)!
self?.intApchIfr = Int(apch_ifr)!
print("string = \(ldg_day) int = \(self.intLdgDay)")
} else {
print("experience for \(snapshot.key) doesn't exist")
}
}
}
您可以使用结构和扩展名对其进行清理。
// Experience.swift
struct Experience {
var ldg_day: String
var ldg_night: String
var apch_ifr: String
}
extension Experience {
static var currentUserRef: DatabaseReference? {
return Auth.auth().currentUser.flatMap {
return Database.database().reference(withPath: "Experience/\($0.uid)")
}
}
init?(snapshot: DataSnapshot) {
guard snapshot.exists() else { return nil }
let value = snapshot.value as? [String:String]
self.ldg_day = value?["LDG_DAY"] ?? "123"
self.ldg_night = value?["LDG_NIGHT"] ?? "0"
self.apch_ifr = value?["APCH_IFR"] ?? "0"
}
}
Etvoilà,
func getUserExp() {
Experience.currentUserRef?.observeSingleEvent(of: .value, with: { [weak self] in
if let experience = Experience(snapshot: $0) {
self?.intLdgDay = Int(experience.ldg_day)!
self?.intLdgNight = Int(experience.ldg_night)!
self?.intApchIfr = Int(experience.apch_ifr)!
print("string = \(experience.ldg_day) int = \(self.intLdgDay)")
} else {
print("experience for \($0.key) doesn't exist")
}
})
}