我有一个代码,通常应该从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获得了好的值.怎么了?我把这段代码用于我的应用程序的许多其他部分,没有问题吗?
谢谢你的帮忙
发布于 2018-12-30 13:52:09
我相信您希望在尝试读取子数据之前确保节点存在。
注:
我看到要读取的路径已经注释掉了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注意,我还用它快速对应的字符串替换了旧的objc NSDictionary : Any
发布于 2018-12-29 17:48:25
假设您的结构来自根,并且Experience包含多个用户ID,您的代码目前正在观察所有用户ID的值,因为/*.child(userID!)*/被注释掉了。
因此,您正在请求每个用户的体验,并在客户端上检查当前用户是否作为子用户存在--如果当前用户的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"
}
}等等,
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")
}
})
}https://stackoverflow.com/questions/53971727
复制相似问题