39

我有一个包含多个对象的 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 对象似乎存在问题。

非常欢迎帮助。

4

5 回答 5

93

如果我正确阅读了文档,这就是您想要的:

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)     
    }
}
于 2014-12-07T11:36:28.840 回答
19

我刚刚将上述答案转换为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)
            }
        })
于 2016-10-20T10:54:44.200 回答
16

这非常易读并且工作正常:

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
      }
})
于 2015-05-21T19:13:59.553 回答
7
   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
       }
   })
于 2016-12-18T17:29:48.987 回答
6

火力基地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)
            }
       }

火力基地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)
            }
       }

如果您有多个键/值,并且想要return使用元素array,请dictionary声明一个数组:

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])
      }
于 2017-10-16T07:10:42.510 回答