使用 Firebase iOS SDK,我尝试从数据库中顶级节点的子节点获取数据,但从中获取数据会为我提供整个顶级节点的数据。
我的数据库中有一个顶级节点。我正在尝试从该节点的直接子节点获取数据。所以,当我在这一行放置断点时:
databaseRef.getData { error, snapshot in
并将
databaseRef
打印到控制台,它会显示子级的 URL。但是,如果我在该闭包内部放置一个断点,并将快照打印到控制台,它将显示父级的数据。我将 Firebase 控制台并排放置,因此我可以清楚地看到它。
我尝试过的事情
databaseRef
的引用并在那里再次打印出来。方法如下:
func getOnce() -> Future<T?, ReceiveError> {
let promise = Promise<T?, ReceiveError>()
let decoder = decoder
let ref = databaseRef // databaseRef is a property on this object
databaseRef.getData { error, snapshot in
print(ref)
// => https://[REDACTED]-default-rtdb.firebaseio.com/invite_codes/jake-email_com for example
print(snapshot)
// => The content of https://[REDACTED]-default-rtdb.firebaseio.com/invite_codes
let result = result(
forError: error,
snapshot: snapshot,
usingDecoder: decoder
)
promise.complete(withResult: result)
}
return promise.future
}
ref
最终如预期的那样:它显示了子级的 url,而
snapshot
显示了父级的数据。如何获取我的数据库参考
https://[REDACTED]-default-rtdb.firebaseio.com/invite_codes
子项的数据库引用是通过获取用户的电子邮件地址并将 @
替换为
-
以及将 .
替换为 _
来创建的。因此,如果我输入 [email protected]
,代码将调用:parentReference.child(encodedEmail)
其中
encodedEmail
是
"jake-some_email"
。当该引用打印到控制台时,其 url 与预期一致,采用以下形式:
https://[REDACTED]-default-rtdb.firebaseio.com/invite_codes/jake-some_email
但是,当我对其调用 getData(completion:
时,我会获取父引用的数据,其中
包含URL 将表示的节点,因为快照最终看起来像这样:
Snap (jake-some_email) {
"jake-someemail_com" = {
// the data that I want
};
"another-email_com" = {
等等等等
注意上面的引用是 TO
jake-some_email
但它也包含
jake-someemail_com
。从 Firebase 控制台查看数据库显示没有与之匹配的结构。extension DatabaseReference {
func toAsyncSnapshot() async -> DataSnapshot {
return await withCheckedContinuation { continuation in
self.observeSingleEvent(of: .value) { snapshot in
continuation.resume(returning: snapshot)
}
}
}
}
这是将回调转换为异步代码时的典型模式;很多语言都实现了它。
这里的延续是某种
deferred
块,它会一直阻塞,直到延续变成
resume
。如果您需要更多上下文,可以搜索 sempahore
或“倒计时锁存器”(这是 Java 特有的)。
如果您对我的解决方法有任何想法,请告诉我,有时我倾向于忽略 Swift 上的重要事情,干杯。
代码:
FirebaseApp.configure()
let data = [ "child" : true, "otherChild": true]
let root = Database.database().reference()
let parentRef = root.child("parent")
let childRef = parentRef.child("child")
parentRef.setValue(data)
childRef.getData { err, snap in
if err != nil {
print("Error: \(err!)")
}
if (snap != nil && snap!.exists()) {
print(childRef)
print(snap!)
}
}
childRef.observeSingleEvent(of:.value, with: { snap in
print("Snapshot from once: \(snap)")
})
parentRef.getData { err, snap in
if err != nil {
print("Error: \(err!)")
}
if (snap != nil && snap!.exists()) {
print(parentRef)
print(snap!)
}
}
这样数据库中的数据就变成了:
https://fir-multi-shards.firebaseio.com/parent/child
Snap (child) 1
Snapshot from once: Snap (child) 1
https://fir-multi-shards.firebaseio.com/parent
Snap (parent) {
child = 1;
otherChild = 1;
}
正如您所看到的,写入的路径和值与我们在代码中的两个引用相匹配。