【问题标题】:Iterate over snapshot children in Firebase迭代 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 对象似乎存在问题。

非常欢迎帮助。

【问题讨论】:

    标签: ios 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) 打印一个整数?
          猜你喜欢
          • 2016-06-05
          • 1970-01-01
          • 2012-12-02
          • 1970-01-01
          • 1970-01-01
          • 2019-05-31
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多