迭代 Firebase 中的子快照
Posted
技术标签:
【中文标题】迭代 Firebase 中的子快照【英文标题】:Iterate over snapshot children in Firebase 【发布时间】:2015-02-05 03:47:17 【问题描述】:我有一个包含多个对象的 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)
)
因此,Swift 迭代 Firebase 返回的 NSEnumerator 对象似乎存在问题。
非常欢迎帮助。
【问题讨论】:
【参考方案1】: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)
Firebase 7.3.0
Database.database().reference().child("key").observe(.value) snapshot in
if let datas = snapshot.children.allObjects as? [DataSnapshot]
let results = datas.compactMap(
($0.value)
)
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】:如果我没看错documentation,这就是你想要的:
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
返回一个包含所有对象的数组,然后可以以通常的方式枚举这些对象。第二种方法从NSEnumerator
一次获取一个对象,并且可能更有效。
在任何一种情况下,被枚举的对象都是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)
【讨论】:
【参考方案3】: 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
)
【讨论】:
【参考方案4】:这很容易阅读并且工作正常:
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
)
【讨论】:
如果我想从 firebase 数据库中删除 someValue 只是那个键,我该怎么做? 对于 SDK v2,我们是否必须在 forloop 中进行承诺回调,确保我们在做其他事情之前完成了所有工作 没有理由打电话给childSnapshotForPath
,每个孩子都已经是一个孩子快照了。【参考方案5】:
我刚刚将上述答案转换为 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)
)
【讨论】:
谢谢它的工作,但print(rest.value)
打印Optional(0)
相反它应该打印一个整数。我怎样才能让print(rest.value)
打印一个整数?以上是关于迭代 Firebase 中的子快照的主要内容,如果未能解决你的问题,请参考以下文章