我已成功从 Firebase 获取数据,但无法将其推送到数组中使用。我的数据库如下:
users
-Wc1EtcYzZSMPCtWZ8wRb8RzNXqg2
-email : "mike@gmail.com"
-lists
-LJiezOzfDrqmd-hnoH-
-owner: Wc1EtcYzZSMPCtWZ8wRb8RzNXqg2
-LJif-UgPgbdGSHYgjY6
-owner: Wc1EtcYzZSMPCtWZ8wRb8RzNXqg2
shopping-lists
-LJh6sdBJtBCM7DwxPRy
-name: "weekly shopping"
-owner: "mike@gmail.com"
登录后我有一个主页,如果存在的话,会在表格上显示现有的购物 list 。在 viewDidLoad() 上,我从用户那里获取购物 list ID,并使用这些 ID 作为引用,从购物 list 中获取详细信息。
但是,我无法设法将这些数据保存到数组中,因为它在关闭后会被删除。我怎样才能以干净的方式做到这一点?
override func viewDidLoad() {
super.viewDidLoad()
SVProgressHUD.show()
tableView.allowsMultipleSelectionDuringEditing = false
// Sets user variable - must have
Auth.auth().addStateDidChangeListener { auth, user in
guard let user = user else { return }
self.user = User(authData: user)
// If new user, write into Firebase
self.usersRef.observeSingleEvent(of: .value, with: { snapshot in
if !snapshot.hasChild(self.user.uid) {
self.usersRef.child(user.uid).setValue(["email": user.email!])
}
})
// Get shopping lists data from "users/lists"
self.usersRef.child(user.uid).child("lists").observe(.value, with: { snapshot in
// Get list IDs
if snapshot.exists() {
if let result = snapshot.children.allObjects as? [DataSnapshot] {
for child in result {
self.listNames.append(child.key)
}
}
}
// Use list IDs - to get details
for item in self.listNames {
let itemRef = self.shoppingListsRef.child(item)
itemRef.observeSingleEvent(of: .childAdded, with: { (snapshot) in
if let value = snapshot.value as? [String: Any] {
let name = value["name"] as? String ?? ""
let owner = value["owner"] as? String ?? ""
let shoppingList = ShoppingList(name: name, owner: owner)
self.items.append(shoppingList)
}
})
}
})
self.tableView.reloadData()
SVProgressHUD.dismiss()
}
}
最佳答案
(这个问题有点不清楚,所以这个答案的几个部分涵盖了所有可能性。这是 Swift 4,Firebase 4/5)
你真的不需要在这里查询,因为你知道你想要哪些节点的键,并且它们将始终按照你的 listNames 数组的顺序读取。这假定 self.listNames 是您要读入的键。
for item in listNames {
let itemRef = shoppingListsRef.child(item)
itemRef.observe(.value, with: { (snapshot) in
if let value = snapshot.value as? [String: Any] {
let name = value["name"] as? String ?? ""
let owner = value["owner"] as? String ?? ""
print(name, owner)
}
})
}
通常,当您在节点内搜索某些内容时会使用查询 - 例如,如果您要查找包含子名称“每周购物”的节点。除此之外,坚持直接读取节点,因为它更快并且开销更少。继续阅读...
我还删除了旧的 NSDictionary 并使用 Swift [String: Any] 并修改了错误检查
然而,真正的问题是通过 .value 读取具有 .observe 的节点。请记住,.value 读取节点的所有子节点,然后需要迭代子节点以获取每个单独的 DataSnapshot。此外, .observe 在节点上留下一个观察者,通知应用程序发生变化,我认为你不想要。所以这将回答发布的问题,(并且需要更好的错误检查)
for item in listNames {
let queryRef = shoppingListsRef
.queryOrdered(byChild: "name")
.queryEqual(toValue: item)
queryRef.observe(.value, with: { (snapshot) in
for child in snapshot.children { //even though there is only 1 child
let snap = child as! DataSnapshot
let dict = snap.value as! [String: Any]
let name = dict["name"] as? String ?? ""
let owner = dict["owner"] as? String ?? ""
print(name, owner)
}
})
}
答案...
这可能是你想要的更多...
for item in listNames {
let queryRef = shoppingListsRef
.queryOrdered(byChild: "name")
.queryEqual(toValue: item)
queryRef.observeSingleEvent(of: .childAdded, with: { snapshot in
let dict = snapshot.value as! [String: Any]
let name = dict["name"] as? String ?? ""
let owner = dict["owner"] as? String ?? ""
print(name, owner)
})
}
请注意 .childAdded 而不是 .value,它将快照呈现为单个 DataSnapshot 并且不需要迭代,而 .observeSingleEvent 不会让观察者附加到每个节点。
编辑
根据附加信息,最好也将结构更改为此
shopping-lists
-LJh6sdBJtBCM7DwxPRy
-name: "weekly shopping"
-uid: "Wc1EtcYzZSMPCtWZ8wRb8RzNXqg2"
然后当用户登录时,只需在购物 list 节点中查询属于他们的任何 uid。
关于swift - 在 Swift 中从 Firebase 快照获取值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51807891/