Reputation: 1643
I've read about a hundred posts on here about dealing with the value of "childByAutoId" children from Firebase's Realtime Database... but I haven't exactly found anything that would explain what I'm trying to do so I figured I'd finally break down and ask.
First off here's the database structure:
let database = Database.database().reference(withPath: "messages")
let db1 = database.child("sender").child("receiver").childByAutoId()
Pretty straightforward. I then wanted to retrieve the value of that autoID.
db1.observeSingleEvent(of: .value, with: { snapshot in
guard let value = snapshot.value as? [String: Any] else{
completion(.failure(DatabaseError.failedToFetch))
print("GetAll Failed")
return
}
...returns the "failedToFetch" error, while:
database.child("sender").child("receiver").observeSingleEvent(of: .value, with: { snapshot in
guard let value = snapshot.value as? [String: Any] else{
completion(.failure(DatabaseError.failedToFetch))
print("GetAll Failed")
return
}
...which is the same thing only excluding childByAutoId returns:
"-MrdAxlUKHvJWjtSQe7X": {
body = "cookies";
createdat = 1640294767943;
msgId = "-MrdAxlUKHvJWjtSQe7X";
name = glynis;
receiverUid = LKJHdhkjhkjsh;
senderUid = LAKSjksljlkajlk;
}
So now the data is coming in... but when I try to get the value of "-MrdAxlUKHvJWjtSQe7X" (the auto-generated key):
let things: [Thing] = value.compactMap({ dictionary in
guard let name = value["name"] as? String,
let msgId = value["msgId"] as? String,
let body = value["body"] as? String,
let receiverUid = value["receiverUid"] as? String,
let senderUid = value["senderUid"] as? String,
let createdat = value["createdat"] as? String,
let dated = value["dated"] as? String,)else {
return nil
}
And I do a:
guard !things.isEmpty else {
print("thing are empty")
return
}
They come up empty (even though "value" is certainly populated.) So my question is how would I properly retrieve the value of the generated key (childByAutoId)?
Upvotes: 0
Views: 90
Reputation: 599776
Some of the problems I spot:
Most of the fields in your value.compactMap(
don't have a matching property in your snapshot just above it. E.g. createdat
is not the same as value["created"]
, and there is no property tId
in the snapshot.
The types need to match up in order to make the as? String
cast work. Your createdat
value is a long number (probably the number of milliseconds since the epoch), so casting that to a string leads to nil
. You should cast it to a long/number value, or convert by calling the String
function, as shown here: Convert Int to String in Swift
Based on your edit...
This code:
database.child("sender").child("receiver").observeSingleEvent(of: .value, with: { snapshot in
Reads the entire sender/receiver
node from your database, which contains one or more child nodes with auto-generated keys, and then properties under each of those child nodes.
When you do:
value = snapshot.value as? [String: Any]
This sets value
to be a dictionary/map with the top-level key(s) being the childByAutoId
. When you then access value["-MrdAxlUKHvJWjtSQe7X"]
you get a map/dictionary with the properties of that child node.
You can also loop over the child nodes of the snapshot with something like:
for child in snapshot.children {
let snap = child as! DataSnapshot //downcast
let dict = snap.value as! [String: Any] // get properties of child node
let msg = dict["body"] as! String
}
Upvotes: 0