每次更换儿童时都会调用Firebase子女

时间:2017-07-11 17:57:37

标签: ios arrays swift firebase firebase-realtime-database

我有一个群发消息应用程序可以正常工作,直到我想要更改一些基本的组属性,如组标题,图像等。在我显示我的代码以显示我的对话并更新它们之前,我将向您展示一些我的数据结构。

在处理对话的显示和编辑时,我使用两个主节点。整个会话节点,包含会话属性和当前用户中的会话节点。

以下是我当前用户的会话节点:

enter image description here

正如您在上图所示,我的用户有一个会话节点,其中包含会话ID列表。这些会话ID指的是我的数据库中的会话节点。这是对话节点的图片:

enter image description here

只是为了回顾一下这个问题。基本上,当我更新任何会话属性(标题,图像,成员)时,它会调用我的子添加方法,这会产生一个错误,我将在稍后显示。

以下是我显示对话的代码:

func observeUserConversations() {
    guard let uid = currentUserProperties.id else {
        return
    }

    FIRDatabase.database().reference().child("users").child(uid).child("conversations").observe(.childAdded, with: { (snapshot) in
        FIRDatabase.database().reference().child("conversations").child(snapshot.key).observe(.value, with: { (conversationSnapshot) in
            if let conversation = Groups(snapshot: conversationSnapshot) {
                conversation.groupId = conversationSnapshot.key

                self.conversations.append(conversation)

                DispatchQueue.main.async(execute: {
                    self.tableView.reloadData()
                })
            }
        }, withCancel: nil)
    }, withCancel: nil)
}

以下是我更新部分会话属性的代码:

static func updateConversationProperties(conversationId: String, property: String, propertyValue: String) {
    let updateConversationPropertyRef = FIRDatabase.database().reference().child("conversations").child(conversationId).child(property)
    updateConversationPropertyRef.setValue(propertyValue)
    ProgressHUD.showSuccess("Field Updated!")
}

请注意我已尝试使用更新子值而不是设置值,但仍然存在相同的错误。

总而言之,每当我更新会话属性时,都会调用子级添加的函数,并将会话的重复版本附加到我的会话数组中。

我知道这可能有点令人困惑,所以我在这里有一个显示错误的视频:  https://youtu.be/OhhnYzQRKi8

在上面的视频中,您会看到相同的对话重复并添加两次。

任何帮助将不胜感激!

更新

所以我改变了观察者看起来像这样:

    FIRDatabase.database().reference().child("users").child(uid).child("conversations").observe(.childAdded, with: { (snapshot) in
        FIRDatabase.database().reference().child("conversations").child(snapshot.key).observeSingleEvent(of: .value, with: { (conversationSnapshot) in
            if let conversation = Groups(snapshot: conversationSnapshot) {
                conversation.groupId = conversationSnapshot.key

                self.conversations.append(conversation)

                DispatchQueue.main.async(execute: {
                    self.tableView.reloadData()
                })
            }
        }, withCancel: nil)
    }, withCancel: nil)

在上面的代码中,一切正常,没有重复。但是,现在对话不会实时更新。相反,它们将显示旧数据,不会更新为新更改的数据。此外,如果我添加对话,则不会显示新添加的对话。

3 个答案:

答案 0 :(得分:2)

以下是我注意到的事项:

您最初获得代码的方式是,只要对/"conversations"/snapshot.key的值进行更改,就会触发第二个侦听器。无论何时进行此调用,您都将conversationSnapshot追加到对话数组:

FIRDatabase.database().reference().child("users").child(uid).child("conversations").observe(.childAdded, with: { (snapshot) in
    FIRDatabase.database().reference().child("conversations").child(snapshot.key).observe(of: .value, with: { (conversationSnapshot) in
        if let conversation = Groups(snapshot: conversationSnapshot) {
            conversation.groupId = conversationSnapshot.key

            self.conversations.append(conversation) // here is where you are appending the data. This will be appended each time a change is made

            DispatchQueue.main.async(execute: {
                self.tableView.reloadData()
            })
        }
    }, withCancel: nil)
}, withCancel: nil)

现在您指出,如果您将FIRDatabase.database().reference().child("conversations").child(snapshot.key).observe更改为.observeSingleEvent,则数据不会再次附加,但您不会获得更新。一种选择是每当触发侦听器时,在数组中搜索快照键,然后在找到时更新该索引处的快照。当然,这不是最有效的方法。

总而言之,听起来确实需要使用observe,但就目前而言,数据是重复的,因为只要对快照进行了更改,代码就会将快照附加到数组的末尾。 39; s值。您必须使用self.conversations.append(conversation)以外的其他内容。

如果您想直接给我留言,我很乐意集体讨论其他一些选择。

答案 1 :(得分:0)

    FIRDatabase.database().reference().child("users").child(uid).child("conversations").observe(.childAdded, with: { (snapshot) in
        FIRDatabase.database().reference().child("conversations").observe(.childAdded, with: { (conversationAdded) in
            if conversationAdded.key == snapshot.key {
                if let group = Groups(snapshot: conversationAdded) {
                    self.conversations.append(group)

                    DispatchQueue.main.async(execute: {
                        self.tableView.reloadData()
                    })
                }
            }
        })
    }, withCancel: nil)

    FIRDatabase.database().reference().child("users").child(uid).child("conversations").observe(.childAdded, with: { (snapshot) in
        FIRDatabase.database().reference().child("conversations").child(snapshot.key).observe(.childChanged, with: { (conversationSnapshot) in
            let conversationIdsArray = self.conversations.map({$0.groupId})

            let changeAtGroupIdIndex = conversationIdsArray.index(of: snapshot.key)

            let conversationToBeUpdated = self.conversations[changeAtGroupIdIndex!]

            conversationToBeUpdated.setValue(conversationSnapshot.value, forKeyPath: conversationSnapshot.key)
            self.tableView.reloadData()
        }, withCancel: nil)
    }, withCancel: nil)

在上面的代码中,我创建了两个不同的观察者。第一个加载应用程序或添加对话时加载对话。如果孩子已被更改,第二个更新会话数组。这解决了这两个问题。

答案 2 :(得分:0)

过滤器数组,其数据不包括刚刚接收的对象。在我的情况下,通过唯一的ID(例如groupID或chatID)在现有数组中标识该对象。然后重复的对象将被删除

self.conversations = self.conversations.filter { obj in (obj.chatId as? String) != (data.chatId as? String) }

self.conversations.append(data)