web-dev-qa-db-ja.com

Firebaseでスナップショットの子を反復処理する

複数のオブジェクトを含む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)     
     }
 })

そのため、Firebaseから返されたNSEnumeratorオブジェクトを繰り返し処理するSwift=に問題があるようです。

ヘルプは大歓迎です。

35
dfucci

documentation rightを読んだ場合、これはあなたが望むものです:

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を必要とし、その後、通常の方法で列挙できます。 2番目のメソッドは、NSEnumeratorから一度に1つずつオブジェクトを取得し、おそらくより効率的です。

どちらの場合も、列挙されるオブジェクトは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)     
    }
}
86
vacawama

上記の答えを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)
            }
        })
17
Ketan P

これは非常に読みやすく、正常に機能します。

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
      }
})
16
Dan
   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
       }
   })
7
Edward

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)
            }
       }

複数のキー/値があり、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])
      }
2
William Hu