迭代 Firebase 中的子快照

Posted

技术标签:

【中文标题】迭代 Firebase 中的子快照【英文标题】:Iterate over snapshot children in Firebase 【发布时间】:2015-02-05 03:47:17 【问题描述】:

我有一个包含多个对象的 Firebase 资源,我想使用 Swift 对它们进行迭代。 我期望的工作如下(根据 Firebase 文档)https://www.firebase.com/docs/ios-api/Classes/FDataSnapshot.html#//api/name/children

var ref = Firebase(url:MY_FIREBASE_URL)
ref.observeSingleEventOfType(.Value, withBlock:  snapshot in
  println(snapshot.childrenCount) // I got the expected number of items
    for rest in snapshot.children  //ERROR: "NSEnumerator" does not have a member named "Generator"
       println(rest.value)     
     
 )

因此,Swift 迭代 Firebase 返回的 NSEnumerator 对象似乎存在问题。

非常欢迎帮助。

【问题讨论】:

【参考方案1】:

Firebase 4.0.1

       Database.database().reference().child("key").observe(.value)  snapshot in
            if let datas = snapshot.children.allObjects as? [DataSnapshot] 
                let results = datas.flatMap(
                  ($0.value as! [String: Any])["xxx"]
                )
                print(results)
            
       

Firebase 7.3.0

       Database.database().reference().child("key").observe(.value)  snapshot in
            if let datas = snapshot.children.allObjects as? [DataSnapshot] 
                let results = datas.compactMap(
                  ($0.value)
                )
                print(results)
            
       

如果您有多个键/值,并且想要 returnarraydictionary 元素,请声明一个数组:

var yourArray = [[String: Any]]()

然后将块体更改为:

     let children = snapshot.children
     while let rest = children.nextObject() as? DataSnapshot, let value = rest.value 
          self.yourArray.append(value as! [String: Any])
      

【讨论】:

【参考方案2】:

如果我没看错documentation,这就是你想要的:

var ref = Firebase(url: MY_FIREBASE_URL)
ref.observeSingleEvent(of: .value)  snapshot in
    print(snapshot.childrenCount) // I got the expected number of items
    for rest in snapshot.children.allObjects as! [FIRDataSnapshot] 
       print(rest.value)     
    

更好的方法可能是:

var ref = Firebase(url: MY_FIREBASE_URL)
ref.observeSingleEvent(of: .value)  snapshot in
    print(snapshot.childrenCount) // I got the expected number of items
    let enumerator = snapshot.children
    while let rest = enumerator.nextObject() as? FIRDataSnapshot 
       print(rest.value)     
    

第一种方法需要NSEnumerator 返回一个包含所有对象的数组,然后可以以通常的方式枚举这些对象。第二种方法从NSEnumerator 一次获取一个对象,并且可能更有效。

在任何一种情况下,被枚举的对象都是FIRDataSnapshot 对象,因此您需要转换才能访问value 属性。


使用for-in循环:

自从在 Swift 1.2 天写出原始答案以来,该语言已经发展。现在可以使用for in 循环直接与枚举器一起使用case let 来分配类型:

var ref = Firebase(url: MY_FIREBASE_URL)
ref.observeSingleEvent(of: .value)  snapshot in
    print(snapshot.childrenCount) // I got the expected number of items
    for case let rest as FIRDataSnapshot in snapshot.children 
       print(rest.value)     
    

【讨论】:

【参考方案3】:
   ref = FIRDatabase.database().reference().child("exampleUsernames")    
   ref.observeSingleEvent(of: .value, with:  snapshot in

       for rest in snapshot.children.allObjects as! [FIRDataSnapshot] 

           guard let restDict = rest.value as? [String: Any] else  continue 
           let username = restDict["username"] as? String
       
   )

【讨论】:

【参考方案4】:

这很容易阅读并且工作正常:

var ref = Firebase(url:MY_FIREBASE_URL)
ref.childByAppendingPath("some-child").observeSingleEventOfType(
  FEventType.Value, withBlock:  (snapshot) -> Void in

      for child in snapshot.children 

        let childSnapshot = snapshot.childSnapshotForPath(child.key)
        let someValue = childSnapshot.value["key"] as! String
      
)

【讨论】:

如果我想从 firebase 数据库中删除 someValue 只是那个键,我该怎么做? 对于 SDK v2,我们是否必须在 forloop 中进行承诺回调,确保我们在做其他事情之前完成了所有工作 没有理由打电话给childSnapshotForPath,每个孩子都已经是一个孩子快照了。【参考方案5】:

我刚刚将上述答案转换为 Swift 3:

ref = FIRDatabase.database().reference()    
ref.observeSingleEvent(of: .value, with:  snapshot in
       print(snapshot.childrenCount) // I got the expected number of items
       for rest in snapshot.children.allObjects as! [FIRDataSnapshot] 
           print(rest.value)
           
)

更好的方法可能是:

    ref = FIRDatabase.database().reference() 
    ref.observeSingleEvent(of: .value, with:  snapshot in
            print(snapshot.childrenCount) // I got the expected number of items
            let enumerator = snapshot.children
            while let rest = enumerator.nextObject() as? FIRDataSnapshot 
                print(rest.value)
            
        )

【讨论】:

谢谢它的工作,但print(rest.value) 打印Optional(0) 相反它应该打印一个整数。我怎样才能让print(rest.value) 打印一个整数?

以上是关于迭代 Firebase 中的子快照的主要内容,如果未能解决你的问题,请参考以下文章

Firebase 实时数据库中的子键问题仅在发布版本中

当数据存在时,Swift firebase 快照返回 null

在 Firebase Firestore 中映射集合快照项

Firebase 实时数据库使快照更有价值

使用 Swift 遍历 Firebase 中的嵌套快照子项

从 Firebase 数据库快照解析布尔值