Swift中字典对象的Firebase实时问题

Posted

技术标签:

【中文标题】Swift中字典对象的Firebase实时问题【英文标题】:Firebase real time issue on dictionary object in Swift 【发布时间】:2019-12-26 09:23:16 【问题描述】:

我正在使用 Firebase 实时获取数据。我的表结构如下。

"Bidding": 
    "-LwyoIpE-obs1244Zflz": 
        "Images": 
            "-LwyoIxdDbabEzKDNjz0": 
                "image": "bookings/15773068970yg5i.png",
                "imgae_key": "-LwyoIxdDbabEzKDNjz0"
            ,
            "-LwyoIxei2rxOOrJAxhD": 
                "image": "bookings/1577306897vIXfc.png",
                "imgae_key": "-LwyoIxei2rxOOrJAxhD"
            
        ,
        "booking_id": "1128",
        "category_id": "4",
        "consumer_id": "143",
        "consumer_image": "/uploads/1576824430.jpeg",
        "created_obj": "2019-12-25 20:48:17",
        "date_time": "2019-12-26 01:47:34",
        "description": "Good",
        "email": "dev@consumer.com",
        "job_type": "1",
        "lat": "37.785834",
        "lng": "-122.406417",
        "order_refrence": "GATK-S-2127",
        "record_id": "-LwyoIpE-obs1244Zflz",
        "sub_category_id": "22",
        "tile": "Contracting works - polish​"
    ,

在视图加载时,我已成功获取“图像”数据。我调用 Firebase 节点并获取图像数据。

Database.database().reference().child("Bidding").observe(.childAdded, with:  (snapshot) in
    if snapshot.exists() 
       let values = snapshot.value as! [String: Any]
       let profile = values["consumer_image"] as? String ?? ""
       let images = values["Images"] as? Dictionary<String, Any>
       print(messages)
    
)

但问题是当节点图像中添加的新子节点实时为零时。当我重新加载视图控制器图像时变得很好。请帮忙。

【问题讨论】:

您的观察者在 Bidding 节点上。这意味着当在 /Bidding/some_new_node 中直接在 Bidding 下添加新节点时,您的 firebase 观察事件将触发。但是,如果您在 Bidding/auto_id/Images 下添加子节点,该事件将不会触发,因为这不是正在观察的节点。你问的是这个吗? 是的。当新的孩子添加到 Firebase 中时,我如何观察图像节点。 添加一个新的子节点.... Bidding 节点的子节点?还是每个用户节点中 Images 节点的子节点? 【参考方案1】:

由于问题仅在您从代码中添加新数据时发生(而不是在您重新加载时),我怀疑您正在添加新节点并多次调用 setValue(...)updateChildValues(...)。例如:

let newChildRef = ref.child("Bidding").childByAutoId()
newChildRef.child("booking_id").setValue("1128")
newChildRef.child("consumer_image").setValue("/uploads/1576824430.jpeg")

在上面的代码中,第一个setValue 调用将触发你的.childAdded 监听器。由于此时您还没有为consumer_image 属性写入值,因此您的侦听器中profile 的值将是nill

setValue 的第二次调用会触发.childChanged 事件,而您并未在监听该事件。

您有两种解决问题的方法:

    在一次写入操作中写入节点的所有属性。 监听节点更新。

在一次写入操作中写入节点的所有属性

为防止.childAdded 在您只为节点写入部分数据时触发,您需要确保在一次调用setValue()updateChildValues() 中写入所有数据。 updating specific property values 上的文档就是一个很好的例子。对于上面的代码 sn-p,这将转换为:

let values = ["booking_id": "1128",
            "consumer_image": "/uploads/1576824430.jpeg"]

ref.child("Bidding").childByAutoId().setValue(values)

由于现在只有一个对 setValues 的调用,您的 .childAdded 侦听器将使用您在该(第一个/唯一)调用中传递的所有值触发。


监听节点更新

上述解决方案的替代方案是使用.childChanged 侦听器侦听节点的更新。在这种情况下,您的侦听器将不得不处理某些属性可能还不存在。

类似:

Database.database().reference().child("Bidding").observe(.childChanged, with:  (snapshot) in
   let values = snapshot.value as! [String: Any]

   if let profile = values["consumer_image"] 
     print(profile)
   
)

【讨论】:

实际上我想在添加新孩子时检索图像数据。我怎样才能得到那个图像节点? 在您当前的数据结构中,这意味着您需要同时监听 childAddedchildChanged 事件。在你当前的结构中没有办法只听图像变化。

以上是关于Swift中字典对象的Firebase实时问题的主要内容,如果未能解决你的问题,请参考以下文章

在 Swift 3 中包含字典的 Firebase 进程子快照

在 Swift 中使用 Alamofire 发送包含字典对象数组的字典对象时会发生奇怪的行为?

如何遍历对象字典及其键

Swift 中的 Firebase 实时数据库

从firebase实时数据库IOS Swift中检索数据

如何在 Swift 中保存实时 Firebase 数据库中的数据?