Firebase观察员两次读取数据

时间:2017-04-18 13:57:38

标签: ios swift firebase firebase-realtime-database

我的观察员会在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的值不同。这是第一室,例如:

enter image description here

工作职能(最终编辑):

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()
    })
}

1 个答案:

答案 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。