SJackson5
SJackson5

Reputation: 47

Firebase snapshot not being cast to dictionary

I have this function that is supposed to fetch data from a comments node from firebase. I want to implement pagination to not load 100+ comments at once. Everything seems to be working but my code seems to be failing at casting the snapchat.value to a Dictionary

     func fetchComments(){
        messagesRef = Database.database().reference().child("Comments").child(eventKey)
        var query = messagesRef?.queryOrderedByKey()
        if comments.count > 0 {
           let value =  comments.last?.commentID
            query = query?.queryStarting(atValue: value)
        }
        query?.queryLimited(toFirst: 2).observe(.childAdded, with: { (snapshot) in

            var allObjects = snapshot.children.allObjects as? [DataSnapshot]

            allObjects?.forEach({ (snapshot) in
                 // print out snapshot and it isn't empty 
                print(snapshot.value) // here it keeps going into the else statement even though snapshot.value clearly exist.

                guard let commentDictionary = snapshot.value as? [String:Any] else{
                    return
                }

                print(commentDictionary)
            })
                   }) { (err) in
            print("Failed to observe comments")
        }
    }

My question is can anyone take a look at this and maybe see where I went wrong? My code looks fine to me and I can't see what's is wrong.

My tree looks like this

"Comments" : {
"CCDS" : {
  "-KrrsXkj6FznzRD0-Xzs" : {
    "content" : "Shawn",
    "profileImageURL" : "https://firebasestorage.googleapis.com/v0/b/eventful-3d558.appspot.com/o/profile_images%2FBC868F8F-E9EC-4B9D-A248-DD2187BC140C.PNG?alt=media&token=fb14700c-2b05-4077-b45c-afd3de705801",
    "timestamp" : 1.503102381340935E9,
    "uid" : "oxgjbrhingbf7vbaHpflhw6G7tB2"
  }
},
"MIA" : {
  "-Krghz9d5_CPjkmdffef" : {
    "content" : "22",
    "profileImageURL" : "https://firebasestorage.googleapis.com/v0/b/eventful-3d558.appspot.com/o/profile_images%2FF50F6915-DEAB-4A5B-B1AB-CABC1E349148.PNG?alt=media&token=4eb7c708-ec87-45bf-952d-0bd410faee50",
    "timestamp" : 1.502915064803007E9,
    "uid" : "oxgjbrhingbf7vbaHpflhw6G7tB2"
  },
  "-KrpoEnNYsmRZ5guORUj" : {
    "content" : "23",
    "profileImageURL" : "https://firebasestorage.googleapis.com/v0/b/eventful-3d558.appspot.com/o/profile_images%2FBC868F8F-E9EC-4B9D-A248-DD2187BC140C.PNG?alt=media&token=fb14700c-2b05-4077-b45c-afd3de705801",
    "timestamp" : 1.503067700479352E9,
    "uid" : "oxgjbrhingbf7vbaHpflhw6G7tB2"
  }
}
  }

Based off my code it bypasses the key and goes straight to the children. For example if pass in MIA it should go to MIA and grab the key corresponding to each comment "-KrrsXkj6FznzRD0-Xzs" and "-KrpoEnNYsmRZ5guORUj" but it is returning everything under that unique ID instead. Which is a problem

Upvotes: 1

Views: 719

Answers (1)

Frank van Puffelen
Frank van Puffelen

Reputation: 598740

The code in your callback seems to assume that you get called with a collection of comments. To get such a collection you need to observe the .value event. When you observe the .value event, you callback gets invoked with a single snapshot that contains all the nodes matching the query:

   query?.queryLimited(toFirst: 2).observe(.value, with: { (snapshot) in

        var allObjects = snapshot.children.allObjects as? [DataSnapshot]

        allObjects?.forEach({ (snapshot) in
            print(snapshot.key)
            print(snapshot.value)

            guard let commentDictionary = snapshot.value as? [String:Any] else{
                return
            }

            print(commentDictionary)
        })
    }) { (err) in
        print("Failed to observe comments")
    }

When you observe .childAdded, your callback instead gets called for every individual node matching the query. That means you need to get rid of a loop in your code:

   query?.queryLimited(toFirst: 2).observe(.childAdded, with: { (snapshot) in
        print(snapshot.key)
        print(snapshot.value)

        guard let commentDictionary = snapshot.value as? [String:Any] else{
            return
        }

        print(commentDictionary)

    }) { (err) in
        print("Failed to observe comments")
    }

Upvotes: 2

Related Questions