首页 > 解决方案 > Swift中字典对象的Firebase实时问题

问题描述

我正在使用 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)
    }
})

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

标签: iosswiftfirebasefirebase-realtime-database

解决方案


由于问题仅在您从代码中添加新数据时发生(而不是在重新加载时),我怀疑您正在添加新节点并多次调用setValue(...)or 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您没有在监听的事件。

您有两个选项可以解决此问题:

  1. 在单个写入操作中写入节点的所有属性。
  2. 监听节点的更新。

在单个写入操作中写入节点的所有属性

为了防止.childAdded在您只为节点写入部分数据时触发 ,您需要确保在一次调用setValue()or中写入所有数据updateChildValues()更新特定属性值的文档就是一个很好的例子。对于上面的代码片段,这将转化为:

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

推荐阅读