草庐IT

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

coder 2023-09-15 原文

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

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

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

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

只是为了检查问题。基本上,当我更新任何对话属性(标题、图像、成员)时,它会重新调用我的 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 - 每次更改子项时都会调用添加的 Firebase 子项的更多相关文章

  1. ruby-on-rails - Ruby on Rails 迁移,将表更改为 MyISAM - 2

    如何正确创建Rails迁移,以便将表更改为MySQL中的MyISAM?目前是InnoDB。运行原始执行语句会更改表,但它不会更新db/schema.rb,因此当在测试环境中重新创建表时,它会返回到InnoDB并且我的全文搜索失败。我如何着手更改/添加迁移,以便将现有表修改为MyISAM并更新schema.rb,以便我的数据库和相应的测试数据库得到相应更新? 最佳答案 我没有找到执行此操作的好方法。您可以像有人建议的那样更改您的schema.rb,然后运行:rakedb:schema:load,但是,这将覆盖您的数据。我的做法是(假设

  2. ruby - 我需要将 Bundler 本身添加到 Gemfile 中吗? - 2

    当我使用Bundler时,是否需要在我的Gemfile中将其列为依赖项?毕竟,我的代码中有些地方需要它。例如,当我进行Bundler设置时:require"bundler/setup" 最佳答案 没有。您可以尝试,但首先您必须用鞋带将自己抬离地面。 关于ruby-我需要将Bundler本身添加到Gemfile中吗?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/4758609/

  3. ruby - 将 Bootstrap Less 添加到 Sinatra - 2

    我有一个ModularSinatra应用程序,我正在尝试将Bootstrap添加到应用程序中。get'/bootstrap/application.css'doless:"bootstrap/bootstrap"end我在views/bootstrap中有所有less文件,包括bootstrap.less。我收到这个错误:Less::ParseErrorat/bootstrap/application.css'reset.less'wasn'tfound.Bootstrap.less的第一行是://CSSReset@import"reset.less";我尝试了所有不同的路径格式,但它

  4. ruby - 续集在添加关联时访问many_to_many连接表 - 2

    我正在使用Sequel构建一个愿望list系统。我有一个wishlists和itemstable和一个items_wishlists连接表(该名称是续集选择的名称)。items_wishlists表还有一个用于facebookid的额外列(因此我可以存储opengraph操作),这是一个NOTNULL列。我还有Wishlist和Item具有续集many_to_many关联的模型已建立。Wishlist类也有:selectmany_to_many关联的选项设置为select:[:items.*,:items_wishlists__facebook_action_id].有没有一种方法可以

  5. ruby-on-rails - 项目升级后 Pow 不会更改 ruby​​ 版本 - 2

    我在我的Rails项目中使用Pow和powifygem。现在我尝试升级我的ruby​​版本(从1.9.3到2.0.0,我使用RVM)当我切换ruby​​版本、安装所有gem依赖项时,我通过运行railss并访问localhost:3000确保该应用程序正常运行以前,我通过使用pow访问http://my_app.dev来浏览我的应用程序。升级后,由于错误Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0,此url不起作用我尝试过的:重新创建pow应用程序重启pow服务器更新战俘

  6. ruby - Capistrano 3 在任务中更改 ssh_options - 2

    我尝试使用不同的ssh_options在同一阶段运行capistranov.3任务。我的production.rb说:set:stage,:productionset:user,'deploy'set:ssh_options,{user:'deploy'}通过此配置,capistrano与用户deploy连接,这对于其余的任务是正确的。但是我需要将它连接到服务器中配置良好的an_other_user以完成一项特定任务。然后我的食谱说:...taskswithoriginaluser...task:my_task_with_an_other_userdoset:user,'an_othe

  7. 使用 ACL 调用 upload_file 时出现 Ruby S3 "Access Denied"错误 - 2

    我正在尝试编写一个将文件上传到AWS并公开该文件的Ruby脚本。我做了以下事情:s3=Aws::S3::Resource.new(credentials:Aws::Credentials.new(KEY,SECRET),region:'us-west-2')obj=s3.bucket('stg-db').object('key')obj.upload_file(filename)这似乎工作正常,除了该文件不是公开可用的,而且我无法获得它的公共(public)URL。但是当我登录到S3时,我可以正常查看我的文件。为了使其公开可用,我将最后一行更改为obj.upload_file(file

  8. ruby - 如何验证 IO.copy_stream 是否成功 - 2

    这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下

  9. ruby-on-rails - 每次我尝试部署时,我都会得到 - (gcloud.preview.app.deploy) 错误响应 : [4] DEADLINE_EXCEEDED - 2

    我是Google云的新手,我正在尝试对其进行首次部署。我的第一个部署是RubyonRails项目。我基本上是在关注thisguideinthegoogleclouddocumentation.唯一的区别是我使用的是我自己的项目,而不是他们提供的“helloworld”项目。这是我的app.yaml文件runtime:customvm:trueentrypoint:bundleexecrackup-p8080-Eproductionconfig.ruresources:cpu:0.5memory_gb:1.3disk_size_gb:10当我转到我的项目目录并运行gcloudprevie

  10. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

随机推荐