我的观察员会在Firebase中侦听添加的新room
,然后在添加一个本地阵列时更新。它正在工作,除非我向Firebase添加一个房间,其中两个房间被添加到阵列中。例如,如果我在Firebase(Room One,Room Two等)中有4个房间,则当应用程序加载时,表格视图中有8个房间(两个房间一个,两个房间等,等等) )。然后添加,例如,五室,两个房间五人将出现。
private func observeRooms() {
guard let uid = FIRAuth.auth()?.currentUser?.uid else {print("Error getting user UID"); return}
let userRoomRef: FIRDatabaseReference = FIRDatabase.database().reference().child("users").child(uid).child("rooms")
userRoomRef.observe(.childAdded, with: { (roomSnap) in
for eachRoom in roomSnap.value as! [String : AnyObject] {
let roomID = eachRoom.key as! String
print("Roomsnap 2 (observer): \(roomSnap.value)")
if let roomInfo = roomSnap.value as? [String : AnyObject] {
guard let roomName = roomInfo["roomName"] as! String! else {print("Error getting room name"); return}
guard let participants = roomInfo["participants"] as! [String]! else {print("Error getting room participants"); return}
print("\n\nRoom Name: \(roomName)\nRoom Participants: \(participants)\nRoom ID: \(roomID)\n")
self.usersRooms.append(Room(id: roomID, name: roomName, participants: participants))
print("User's Rooms: \(self.usersRooms)\n")
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
}
})
}
为什么数据被提取两次?有没有办法写这个函数只读一次房间?
Firebase DB JSON:
"tzfHgGKWLEPzPU9GvkO4XE1QKy53" : {
"gender" : "male",
"handle" : "TestHandleOne",
"name" : "Timothy",
"profilePicture" : "https://graph.facebook.com/*removed*/picture?type=large&return_ssl_resources=1",
"rooms" : {
"-KhY2GnJOxBwdPK669ui" : {
"participants" : [ "tzfHgGKWLEPzPU9GvkO4XE1QKy53" ],
"roomName" : "Room One"
},
"-KhY2Hnz48lTtRpzmBuw" : {
"participants" : [ "tzfHgGKWLEPzPU9GvkO4XE1QKy53" ],
"roomName" : "Room Two"
},
"-KhY2IZL4l16dMxGopt6" : {
"participants" : [ "tzfHgGKWLEPzPU9GvkO4XE1QKy53" ],
"roomName" : "Room Three"
},
"-KhY8SdHnkfI7bZIpyjI" : {
"participants" : [ "tzfHgGKWLEPzPU9GvkO4XE1QKy53" ],
"roomName" : "Room Four"
}
}
}
roomSnap.value
打印到控制台,每个房间打印两次,房间ID的值不同。这是第一室,例如:
工作职能(最终编辑):
private func observeRooms() {
guard let uid = FIRAuth.auth()?.currentUser?.uid else {print("Error getting user UID"); return}
let userRoomRef: FIRDatabaseReference = FIRDatabase.database().reference().child("users").child(uid).child("rooms")
roomRefHandle = userRoomRef.observe(.childAdded, with: { (snapshot) -> Void in
let roomData = snapshot.value as! Dictionary<String, AnyObject>
let id = snapshot.key
guard let name = roomData["roomName"] as! String! else {print("Error getting user name"); return}
self.usersRooms.append(Room(id: id, name: name, participants: [uid]))
// Add new room to "rooms" in Firebase
let roomDict = ["roomName" : name, "participants": [uid]] as [String : Any]
let newRoomRef = self.roomRef.child(id)
newRoomRef.setValue(roomDict)
self.tableView.reloadData()
})
}
答案 0 :(得分:1)
.childAdded函数在第一次调用时一次一个地读取每个子节点,然后读取任何新的子节点。
此事件将针对每个现有子项触发一次,然后再触发一次 每次将新子项添加到指定路径时。听众是 传递了包含新孩子数据的快照。
这里的关键是它一次一个地自动迭代节点中的每个房间。问题中的代码是冗余的,这会导致数组中的多个条目。
这是使用每个子节点填充数组的超短方法
let usersRef = self.ref.child("users")
let uid = "user_0" //some uid
let userRoomRef = usersRef.child(uid).child("rooms")
userRoomRef.observe(.childAdded, with: { roomSnap in
let roomDict = roomSnap.value as! [String: AnyObject]
let roomID = roomSnap.key
let roomName = roomDict["roomName"] as! String
print("roomID = \(roomID) roomName = \(roomName)")
var aRoom = Room() //could also initWith...
aRoom.id = key
aRoom.name = roomName
//aRoom.participants = partipants
self.usersRooms.append(aRoom)
self.tableView.reloadData()
})
修改强>
在回应评论时,另一种结构是
users
uid_0
name: "Tom"
uid_1
name: "Jerry"
rooms
room_0
name: "Cool Room"
users:
uid_0: true
uid_1: true
room_1
name: "Romper Room"
users
uid_0: true
Tom和Jerry都属于Cool Room,但只有Tom属于Romper Room。
如果你想用Tom所属的房间填充数组/ tableView,你可以简单地深入查询房间/用户/ uid_0 == true。