我的Firebase实时数据库的结构如下:
{
"friends" : {
"-LhZw8ryHbE-VIeh1kx6" : {
"members" : [ "3rTK12GBEQf8WMbLEdAz4Pftkxs1", "guHd7whcqyfFjfkduPoCmryLe0I3" ],
"title" : "Ansh’s Trials"
},
"-LhdBeCVRfDVQBtoAeuf" : {
"members" : [ "3rTK12GBEQf8WMbLEdAz4Pftkxs1", "guHd7whcqyfFjfkduPoCmryLe0I3" ],
"title" : "Trial 2"
},
},
"users" : {
"3rTK12GBEQf8WMbLEdAz4Pftkxs1" : {
"email" : "anshgodha77@gmail.com",
"fullname" : "Ansh Godha",
"provider" : "Firebase"
},
"guHd7whcqyfFjfkduPoCmryLe0I3" : {
"email" : "harvey@davidson.com",
"fullname" : "Harvey Davidson",
"provider" : "Firebase"
}
}
}
现在,在应用程序中,我创建了用户组,如您所见,每个组都添加在数据库的“朋友”下。我试图在表视图中检索所有组。在这个表视图中,我将组标题设置为“friends”子树中相应组的“title”值。给定组键,设置标题很简单。然而,似乎我在检索组中人员的姓名时遇到了问题。注意,要在我的模型中存储一个组,我将用户的uid存储在该特定组中(请参阅JSON树)。以下是我尝试执行此操作的方法(有关代码的其他信息,请参阅下面的指针):
func getUserFullname(forUID uid: String, handler: @escaping (_ username: String) -> ()) {
print(5)
self.REF_USERS.observeSingleEvent(of: .value) { (userSnapshot) in
print(6)
guard let userSnapshot = userSnapshot.children.allObjects as? [DataSnapshot] else { return }
print(7)
for user in userSnapshot {
print(8)
if user.key == uid {
handler(user.childSnapshot(forPath: "fullname").value as! String)
}
}
}
}
func getFullnameList(fromUIDArray uidarr: [String], completion: @escaping (_ nameArr: [String]) -> ()){
var namearr = [String]()
print(1)
for uid in uidarr {
print(2)
DataService.instance.getUserFullname(forUID: uid) { (returnedFullName) in
namearr.append(returnedFullName)
}
print(3)
}
print(4)
completion(namearr)
}
REF_用户定义为
Database.database().reference().child("users")
DataService
是定义了这两种方法的单例。我知道代码背后的逻辑是正确的,因为当我打印结果时,我可以看到正确的名称。只是在代码的所有其他部分完成执行之后,我看到了名称。实际上,
nameArr
是一个空数组,即使在第二个方法的末尾。那么,如何才能使用户名正确传递到
nameArr
?我试着引用所有其他的SO帖子,它们似乎都是这样使用完成处理程序的。谢谢!PS:我对Swift和IOS AppDev非常陌生,如果这仍然是一个非常常见的问题,我很抱歉!但是我试着实现我在网上找到的不同的东西(比如DispatchQueues),但是没有成功:(。此外,这是我的第一个StackOverflow帖子之一,所以很抱歉,如果它缺乏细节。将发布更多需要的信息!
最佳答案
我建议换一种结构。阵列在NoSQL数据库中具有固有的挑战性,通常有更好的选择。
假设用户节点
users
uid_0
name: "Bill"
uid_1
name: "Ted"
以及一个提议的群组结构
groups
group_0
name: "My Most Excellent Group"
members:
uid_0: true
uid_1: true
然后一些代码来读取组,打印标题,然后遍历成员列表中的每个子项,从users节点获取成员名称并打印出来。我添加了一些注释,这样您可以更轻松地遵循代码。
func readGroups() {
let groupsRef = self.ref.child("groups")
groupsRef.observeSingleEvent(of: .value, with: { snapshot in //read all groups at once
let allGroupsArray = snapshot.children.allObjects as! [DataSnapshot] //put each child into an array as a DataSnapshot
for groupSnap in allGroupsArray { //iterate over the array so we can read the group name and group members
let groupName = groupSnap.childSnapshot(forPath: "title").value as? String ?? "No Group Name"
print("group: \(groupName) has the following members")
let members = groupSnap.childSnapshot(forPath: "members") //get the members child as a DataSnapshot
let allMembers = members.children.allObjects as! [DataSnapshot] //put the members into an array
for memberSnap in allMembers {
let memberUid = memberSnap.key //get the uid of each member
let memberRef = self.ref.child("users").child(memberUid) //get a reference to the member
memberRef.observeSingleEvent(of: .value, with: { childSnap in //read the member in, print name
let name = childSnap.childSnapshot(forPath: "name").value as? String ?? "No Name"
print(" name: \(name)")
})
}
}
})
}
输出将是
group: My Most Excellent Group has the following members
name: Bill
name: Ted