realtime query datasnapshot consultas arquitectura ios swift firebase nsenumerator

query - realtime database firebase ios



Iterar sobre niños instantáneos en Firebase (5)

Tengo un recurso de Firebase que contiene varios objetos y me gustaría iterar sobre ellos usando Swift. Lo que esperaba que funcione es lo siguiente (de acuerdo con la documentación de 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) } })

Entonces parece que hay un problema con Swift iterando sobre el objeto NSEnumerator devuelto por Firebase.

La ayuda es realmente bienvenida.


Acabo de convertir la respuesta anterior a 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) } })

Una mejor manera podría ser:

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


Esto es bastante legible y funciona bien:

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


Si leo la documentation correctamente, esto es lo que quieres:

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

Una mejor manera podría ser:

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

El primer método requiere que NSEnumerator devuelva una matriz de todos los objetos que luego se pueden enumerar de la manera habitual. El segundo método obtiene los objetos uno por uno del NSEnumerator y es probable que sea más eficiente.

En cualquier caso, los objetos que se enumeran son objetos FIRDataSnapshot , por lo que necesita las conversiones para poder acceder a la propiedad de value .

Usando for-in loop:

Desde que escribí la respuesta original en Swift 1.2 días, el lenguaje ha evolucionado. Ahora es posible usar un bucle for in que funciona directamente con los enumeradores junto con case let para asignar el tipo:

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


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

Si tiene varias claves / valores y desea return una array con elementos de dictionary , declare una matriz:

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

luego cambie el cuerpo del bloque a esto:

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


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