通过嵌套的Firebase数据循环填充数组Swift [英] Fill an array through a nested Firebase data loop Swift
问题描述
我想通过从一个Firebase节点获取值来填充数组,并使用这些值从另一个Firebase节点获取信息.我该怎么办?
I want to fill an array by fetching values from one firebase node and use those values to fetch information from a different firebase node. How do I do that?
这是我的Firebase数据库的样子:
This is what my firebase database looks like:
{
"MainTree" : {
"subTree1" : {
"JiRtkpIFLVFNgmNBpMj" : {
"PiRterKFLVFNgmFFFtu" : "PiRterKFLVFNgmFFFtu"
"TfRterKFLVFNgmFGFre" : "TfRterKFLVFNgmFGFre",
"X4RterKFLVFNgmaDFca" : "X4RterKFLVFNgmaDFca"
}
},
"subTree2" : {
"PiRterKFLVFNgmFFFtu" : {
"username" : "user1",
"uid" : "PiRterKFLVFNgmFFFtu"
},
"TfRterKFLVFNgmFGFre" : {
"username" : "user2",
"uid" : "TfRterKFLVFNgmFGFre"
},
"X4RterKFLVFNgmaDFca" : {
"username" : "user3",
"uid" : "X4RterKFLVFNgmaDFca"
}
}
}
}
我的功能
func fetchAllInformation(uid: String, completion: @escaping ([UserData]) -> (), withCancel cancel: ((Error) -> ())?) {
let ref = Database.database().reference().child("MainTree").child("subTree1").child(uid)
ref.observeSingleEvent(of: .value, with: { (snapshot) in
if snapshot.exists(){
guard let dictionaries = snapshot.value as? [String: Any] else {
completion([])
return
}
var Values = [UserData]()
let group = DispatchGroup()
dictionaries.forEach({ (key, value) in
group.enter()
let ref = Database.database().reference().child("MainTree").child("subTree2").child(key)
ref.observeSingleEvent(of: .value, with: { (snapshot) in
guard let userDictionary2 = snapshot.value as? [String: Any] else { return }
let user = UserData(dictionary: userDictionary2)
Values.append(user)
}) { (err) in
print("Failed to fetch all user data from database:", (err))
cancel?(err)
}
})
group.notify(queue: .main) {
print("loop done")
completion(Values)
}
}
}) { (err) in
print("Failed to fetch all data from database:", (err))
cancel?(err)
}
}
我的通话功能:
fetchAllInformation(uid: "JiRtkpIFLVFNgmNBpMj", completion: { (userdata) in
print("fetched all userdata! : ",userdata)
}) { (err) in
print("data fetch failed")
}
我的数据结构
struct UserData {
let uid: String
let username: String
init(dictionary: [String: Any]) {
self.uid = dictionary["id"] as? String ?? ""
self.username = dictionary["username"] as? String ?? ""
}
}
对异步代码可能是一种误解.现在的问题是数组变成空的.
It might be a misunderstanding with asynchronous code. Right now the problem is that the array is turning up empty.
推荐答案
我认为您要问的是如何遍历一系列节点,如何从该节点获取另一个节点的子键,然后从另一个节点读取数据这些键为基础的节点.
I think what's you're asking is how to iterate over a series of nodes, getting another nodes child keys from that node, then reading the data from the other node based on those keys.
让我从一个Firebase结构开始,该结构应该有助于阐明
Let me start with a Firebase structure that should help clarify
MainTree
subTree1
some_node
subTree2_0: true
subTree2_1: true
subTree2_2: true
subTree2
subTree2_0:
user_name: "Larry"
subTree2_1:
user_name: "Moe"
subTree2_1:
user_name: "Curly"
那应该符合问题的结构.
That should match up to the structure in the question.
我们将遍历MainTree/subTree1/some_node中的子节点,以获取要从subTree2中读取的节点.我不知道与其余数据有关的some_node是什么,所以我将其称为... some_node.
We're going to iterate over the child nodes located in MainTree/subTree1/some_node to get the nodes we want to read from subTree2. I didn't know what some_node was in respect to the rest of the data so I just called it... some_node.
第一部分代码立即读取subTree1节点的子节点,然后对其进行迭代以获取每个子键-该子键(例如subTree2_0)对应于subTree2中的一个子节点
This first section of code reads the subTree1 node child nodes at once, then iterates over them to get each child key - that child key (e.g. subTree2_0) corresponds to a child node in subTree2
func readMainTree() {
let mainTreeRef = self.ref.child("MainTree")
let subTree1Ref = mainTreeRef.child("subTree1")
let someNodeRef = subTree1Ref.child("some_node")
someNodeRef.observeSingleEvent(of: .value, with: { snapshot in
let childNodes = snapshot.children.allObjects as! [DataSnapshot]
for childSnap in childNodes {
self.readSubTree2At(node: childSnap.key)
}
})
}
在for..loop内,我们获得每个子键,并将其传递给读取子数据(用户名)并打印出来的函数.
Within the for..loop, we get each child key and pass that to the function that reads the child data (user_name) and prints it out.
func readSubTree2At(node: String) {
let mainTreeRef = self.ref.child("MainTree")
let subTree2Ref = mainTreeRef.child("subTree2")
let childRef = subTree2Ref.child(node)
childRef.observeSingleEvent(of: .value, with: { snapshot in
let userName = snapshot.childSnapshot(forPath: "user_name").value as? String ?? "No Name"
print(userName)
})
}
,输出为:
Larry
Mo
Curly
如果需要,可以将dispatchGroup放入混合中.这是使用DispatchGroup的解决方案
You could throw a dispatchGroup into the mix if you want.. here's a solution using a DispatchGroup
func readMainTreeWithDispatch() {
let mainTreeRef = self.ref.child("MainTree")
let subTree1Ref = mainTreeRef.child("subTree1")
let someNodeRef = subTree1Ref.child("some_node")
someNodeRef.observeSingleEvent(of: .value, with: { snapshot in
let childNodes = snapshot.children.allObjects as! [DataSnapshot]
let myGroup = DispatchGroup()
for childSnap in childNodes {
let mainTreeRef = self.ref.child("MainTree")
let subTree2Ref = mainTreeRef.child("subTree2")
let childRef = subTree2Ref.child(childSnap.key)
myGroup.enter()
childRef.observeSingleEvent(of: .value, with: { snapshot in
let userName = snapshot.childSnapshot(forPath: "user_name").value as? String ?? "No Name"
print(userName)
myGroup.leave()
})
}
myGroup.notify(queue: .main) {
print("Finished reading all user names.")
}
})
}
和输出
Larry
Mo
Curly
Finished reading all user names.
这篇关于通过嵌套的Firebase数据循环填充数组Swift的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!