【问题标题】:Getting a nil value from Firebase using Swift使用 Swift 从 Firebase 获取 nil 值
【发布时间】:2018-04-30 13:28:30
【问题描述】:

我已经尝试了五天了,但没有运气。

这是我的 Firebase 快照:

Snap (Channels) {
    HiruFM =     {
        image = "hiru_fm_logo.png";
        title = "Hiru FM";
    };
    SirasaFM =     {
        image = "sirasa_fm_logo.png";
        title = SirasaFM;
    };
}

以下是我尝试过的:

override func viewDidLoad() {
    super.viewDidLoad()

    ref = Database.database().reference().child("Channels")

    ref.observeSingleEvent(of: .value) { (snap) in
        print(snap) // checking if the snap grabs the data (confirmed)
        guard var data = snap.value as? Dictionary<String, Any> else {return}


        let channeTitle = data["title"] as? String ?? "No title"
        print(channeTitle) // prints "No title" (this is the problem)

        let channelImage = data["image"] as? String ?? "No image"
        print(channelImage) // prints "No image"
        let myData = Channels(title: channeTitle, image: channelImage)
        self.channels.append(myData)
    }
}

【问题讨论】:

  • data 中存在哪些键?
  • 只有字符串值
  • 这不是我问的。您正在尝试访问键“标题”和“图像”,但它们似乎不存在。实际存在哪些键?
  • 它在频道 > 子类别中。我可以专门深入研究这些类别,但是如果我有 100 个类别的快照(频道){ HiruFM = { image = "hiru_fm_logo.png";标题 = "Hiru FM"; }; SirasaFM = { image = "sirasa_fm_logo.png";标题=SirasaFM; }; }
  • 你的问题。你有一本字典。

标签: json swift database firebase


【解决方案1】:

了解通过 .value 和 .childAdded 读取节点之间的区别很重要,另一个考虑因素是将父节点键与其包含的数据分离。

从以下结构开始

channels
  chan_0
    image: "hiru_fm_logo.png"
    name: "HiruFM"
    title "Hiru FM"
  chan_1
    image: "sirasa_fm_logo.png"
    name: "SirasaFM"
    title "Sirasa FM"

chan_0、chan_1 等键是使用 childbyAutoId 创建的,并允许将键与子数据分离。这样,如果其中一个子值发生变化,它会保持父节点和引用它的其他节点之间的完整性。实际上,如果 HiruFM 变成 HiruXM,只需更改子节点,而不是父节点。

然后是保存数据的结构。请注意,结构 init 会分解快照并分配属性

struct ChannelStruct{
    var image = ""
    var title = ""
    var name = ""

    init(aSnap: DataSnapshot) {
        let dict = aSnap.value as! [String: Any]

        if let image = dict["image"] as? String {
            self.image = image
        }

        if let title = dict["title"] as? String {
            self.title = title
        }

        if let name = dict["name"] as? String {
            self.name = name
        }
    }
}

和一个类数组来保存结构

var channels = [ChannelStruct]()

最后是读取节点的代码并遍历子节点以将它们添加到数组中

ref = Database.database().reference().child("channels")
ref.observeSingleEvent(of: .value) { snapshot in
    if snapshot.exists() {
        for child in snapshot.children {
            let snap = child as! DataSnapshot
            let aChannel = ChannelStruct(aSnap: snap)
            self.channels.append(aChannel)
        }
    } else {
        print("no channels found")
    }
}

注意,通过.value读取时,父节点,channels,所有的子节点都被读入,所以需要迭代获取每个子节点——这也保持了它们的顺序。然而,如果我们使用 .childAdded,它会呈现每个子节点,一次一个,因此不需要迭代。

【讨论】:

    【解决方案2】:

    我觉得你应该试试

    for imageData in data
    {
        let item:NSDictionary = imageData as NSDictionary
        let channeTitle = data["title"] as? String ?? "No title"
        print(channeTitle)
        let channelImage = data["image"] as? String ?? "No image"
        print(channelImage) 
        let myData = Channels(title: channeTitle, image: channelImage)
        self.channels.append(myData)
    }
    

    这里如果你需要先获取字典的数据,你需要先获取每个数据,然后循环获取它们的子节点数据。

    【讨论】:

    • 谢谢,让 item:NSDictionary = imageData as NSDictionary 这给了我一个错误。说(无法将类型“(键:字符串,值:任意)”的值转换为强制类型“NSDictionary”)
    • 不要在 Swift 中使用 NSDictionary。使用 Swift 字典。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-26
    • 1970-01-01
    相关资源
    最近更新 更多