ios - 每次更改子项时都会调用添加的 Firebase 子项

标签 ios arrays swift firebase firebase-realtime-database

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

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

这是我当前用户的对话节点的样子:

enter image description here

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

enter image description here

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

这是我显示对话的代码:

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)

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

最佳答案

这是我注意到的:

按照您最初拥有代码的方式,只要对 /"conversations"/snapshot.key 的值进行更改,就会触发第二个监听器。每当进行此调用时,您都会将 conversationSnapshot 附加到 conversations 数组:

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,但就目前而言,数据是重复的,因为每当对快照的值。您将不得不使用 self.conversations.append(conversation) 以外的东西。

如果您想直接给我发消息,我很乐意集思广益一些其他选择。

关于ios - 每次更改子项时都会调用添加的 Firebase 子项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45041559/

相关文章:

ios - 在 Swift 中设置导航栏高度

带有振动的iOS自定义键盘

java - List<Byte> to String,你能帮忙重构这个(小)方法吗?

ios - 我如何获取 JT Apple 日历 View 的 indexpath.section

swift - 更新 View 时处理单击和双击

ios - 未为 ChildViewController 更新父变量

ios - 核心图形中三角函数定义的梯度

Python 颜色图,但所有零值都映射为黑色

javascript - 我的程序适用于 array::forEach 但不适用于 for 循环

ios - 如何在 Swift 中根据外部事件更新变量?