Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Iterate over snapshot children in Firebase

I have a Firebase resource that contains several objects and I would like to iterate over them using Swift. What I expected to work is the following (according to the Firebase documentation)
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)           }  }) 

So it seems there is a problem with Swift iterating over the NSEnumerator object returned by Firebase.

Help is really welcome.

like image 635
dfucci Avatar asked Dec 07 '14 10:12

dfucci


2 Answers

If I read the documentation right, this is what you want:

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

A better way might be:

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

The first method requires the NSEnumerator to return an array of all of the objects which can then be enumerated in the usual way. The second method gets the objects one at a time from the NSEnumerator and is likely more efficient.

In either case, the objects being enumerated are FIRDataSnapshot objects, so you need the casts so that you can access the value property.


Using for-in loop:

Since writing the original answer back in Swift 1.2 days, the language has evolved. It is now possible to use a for in loop which works directly with enumerators along with case let to assign the type:

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)          } } 
like image 197
vacawama Avatar answered Oct 05 '22 23:10

vacawama


I have just converted the above answer to 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)            } }) 

A better way might be:

    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)             }         }) 
like image 36
Ketan P Avatar answered Oct 05 '22 22:10

Ketan P