0

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

mystic cola
  • 1,465
  • 1
  • 21
  • 39

1 Answers1

0

Some of the problems I spot:

  1. 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.

  2. 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
}
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • Ah... It's Frank again! (Hi, Frank!) So the fields in the value.compactMap I just made up. They match in the real thing. My big question is really about the childByAutoId... assuming everything is matching up correctly... should the "things" be populated the way that "value" is now? – mystic cola Dec 28 '21 at 20:47
  • I recommend not making things like that up going forward, so as to not waste the time of folks who try to help you. It might be a good moment to reread [how to create a minimal, complete, verifiable example](http://stackoverflow.com/help/mcve) --- If you're using the value of `childByAutoId` correctly, you can use it to read the data back. But you're not using the value of `childByAutoId` anywhere in the code in your question, so it's hard to say what's going wrong. Are `db1` (which is never used after its initialized) and `guid` (which is never initialized) somehow related? – Frank van Puffelen Dec 28 '21 at 21:02
  • Apologies. I was typing the question too-fast. The reason I haven't included childByAutoId in the code was because it never returned a value. Db1 is the path before you get to any of the child nodes. guid is the first child node and self.fid2 is the second. The childByAutoId is the key that's generated for the object container. the "value" code I've written above returns objects such as the one listed below it. If I did "database.child(self.fid2).child(guid).childByAutoId().observeSingleEvent...) instead... it would return nothing. – mystic cola Dec 28 '21 at 21:27
  • Instead of trying to clarify here in comments, can you edit your question to show a [single code snippet that reproduces the problem](http://stackoverflow.com/help/mcve)? Don't show us in words, what you can show in code e.g. "guid is the first child node" is really hard to parse - but if you edit your question to show how `guid` is initialized, we'll have a much better chance at figuring out what's going on and helping you. – Frank van Puffelen Dec 28 '21 at 22:01
  • I have tried my level best to edit the question and clarify things. If it still isn't clear... then I will simply delete the question and apologize once again for wasting your time. – mystic cola Dec 28 '21 at 22:36
  • Added an update... – Frank van Puffelen Dec 28 '21 at 22:56
  • @mysticcola Any progress here? – Frank van Puffelen Dec 30 '21 at 01:20