2017-02-10 74 views
0

如何访问处于“更深”级别快照中的信息?我是否总是需要启动另一个查询?为了向你展示我的意思,我有我的结构的截图: Screenshot of DataStructureFirebase中的嵌套信息

我加载所有的职位我的查询中,我可以读出作者的信息等,但我怎么能进去选项中的信息?我试过如下:

ref.child("posts").child("details").observe(.childAdded, with: { (snapshot:FIRDataSnapshot) in 

     if snapshot.value == nil { 
      return 
     } 
     let post = Post() 
     guard let snapshotValue = snapshot.value as? NSDictionary else { 
      return 
     } 
     post.postID = snapshot.key 
     post.title = snapshotValue["title"] as? String 
     post.postDescription = snapshotValue["description"] as? String 
     if (post.postDescription == ""){ 
      post.postDescription = "No description has been entered for this post.." 
     } 
     post.timestamp = snapshotValue["timestamp"] as? NSNumber 

     let options = snapshotValue["options"] 
     print(options) 

当我打印选项,我可以看到的信息,但是当我尝试将其转换为NSDictionary中或东西来访问它,它打印零?我也可以定义一个新的属性,如post.options,如果这可能有所帮助?选项并不总是只有0和1,它的变量,所以我需要遍历这些。我怎样才能做到这一点?

+0

如果我理解正确,'print(options)'实际上会打印您的数据,对吧?从图像看来,选项虽然是一个数组,但如果将它转换为字典,它将不起作用。也许通过for ... each循环遍历选项并打印内容以查看您是否获得了数据 – Prientus

+0

好的我会尝试 –

+0

我需要以某种方式进行投射,否则选项的类型为Any?..所以我可以' t使用每个循环的类型 –

回答

0

跟进原题的评论,你可以访问选项值如下:

if let options = snapshotValue["options"] as? [Any] { 
    for option in options { 
     if let optionDict = option as? [String:Any] { 
      let votes = optionDict["votes"] as? Int 
      let url = optionDict["uri"] as? String 
     } 
    } 
} 
+0

@cloo_coder否否否。这不是一个好的答案。虽然它有时会*有效*,如果options是一个String或一个Bool?你假设选项是一个它*不是的字典* - 它是一个通常应该避免的[数组是邪恶的] Firebase数组(https://firebase.googleblog.com/2014/04/best-practices-array -in-firebase.html) – Jay

+0

@Jay你是对的,mainArray是不正确的和随机的,我把它改回到'options',因为它应该是。我不明白的是,如果OP知道'options'是Firebase子项,他知道它是一个项目列表,为什么他不能把它当作一个'[Any]'? – Prientus

+0

当定义为Any时,snapshotValue的值不会为[“options”]。自行运行代码,您会发现OP的结构始终为零。 – Jay

0

这里有一个大大简化的答案,将与提出的火力地堡结构(注意火力地堡阵列的应该只是工作在特定情况下使用,一般应避免)。

给定一个结构

posts 
    post_id_0 
    caption: "some caption" 
    comment: "some comment" 
    options: 
     0: 
      votes: "10" 
      url: "some url" 
     1: 
      votes: "20" 
      url: "some url" 

说明该结构类似于在该选项的孩子节点的OP是火力地堡阵列,其中每个索引还包含子节点。因此,关键是索引(0,1,2),每个子项都是一个关键字:值对(票:value和url:value)的字典

下面的代码将在此特定节点中读取print标题和评论,然后遍历options数组并打印每个儿童票和URL数组中

ref.child("posts").child("post_id_0") 
        .observeSingleEvent(of: .value, with: { snapshot in 
    //treat the whole node as a dictionary 
    let postDict = snapshot.value as! [String: Any] 

    //and since it's a dictionary, access each child node as such  
    let caption = postDict["caption"] as! String 
    let comment = postDict["comment"] as! String 

    print("caption: \(caption) comment: \(comment)") 

    //the options child node is an array of indexes, each with 
    // a dictionary of child nodes  
    let options = postDict["options"] as! [[String:Any]] //array of dictionaries 

    //now iterate over the array  
    for option in options { 
      let votes = option["votes"] //each option child is a dict 
      let url = option["url"] 
      print("votes \(votes!) url: \(url!)") 
    } 
}) 

请注意,我们表示选择子节点的这样

let options = postDict["options"] as! [[String:Any]] 

结构这是一个key:value(String:Any)字典数组

非常重要的一点是,必须读入整个选项节点才能使用它。如果有10k个孩子,它会变得非常低效。它也不是可查询的,所以如果你想要统计有多少重复url,那么整个节点必须被读入然后解析。

一个更好的选择是使用childByAutoId创建节点键名

posts 
    post_id_0 
    caption: "some caption" 
    comment: "some comment" 
    options: 
     -Yuijjismisdw 
      votes: "10" 
      url: "some url" 
     -YJ989jijdmfm 
      votes: "20" 
      url: "some url" 

Yuijjismisdw与childByAutoId创建。