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