J'ai une ressource Firebase qui contient plusieurs objets et je voudrais les parcourir en utilisant Swift. Ce que je m'attendais à travailler est le suivant (selon la documentation 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)
}
})
Il semble donc qu'il y ait un problème avec Swift itération sur l'objet NSEnumerator retourné par Firebase.
L'aide est vraiment la bienvenue.
Si je lis le documentation à droite, voici ce que vous voulez:
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)
}
}
Une meilleure façon pourrait être:
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)
}
}
La première méthode nécessite que NSEnumerator
retourne un tableau de tous les objets qui peuvent ensuite être énumérés de la manière habituelle. La deuxième méthode obtient les objets un par un à partir de NSEnumerator
et est probablement plus efficace.
Dans les deux cas, les objets énumérés sont des objets FIRDataSnapshot
, vous avez donc besoin des transtypages pour pouvoir accéder à la propriété value
.
Utilisation de for-in
boucle:
Depuis la réécriture de la réponse d'origine en Swift 1,2 jours, la langue a évolué. Il est désormais possible d'utiliser un for in
boucle qui fonctionne directement avec les énumérateurs avec case let
pour affecter le 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)
}
}
Je viens de convertir la réponse ci-dessus en 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)
}
})
Une meilleure façon pourrait être:
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)
}
})
Ceci est assez lisible et fonctionne très 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
}
})
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
}
})
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 vous avez plusieurs clés/valeurs et que vous souhaitez return
an array
avec dictionary
éléments, déclarez un tableau:
var yourArray = [[String: Any]]()
puis changez le corps du bloc en ceci:
let children = snapshot.children
while let rest = children.nextObject() as? DataSnapshot, let value = rest.value {
self.yourArray.append(value as! [String: Any])
}