SJackson5 SJackson5 - 1 month ago 11
Swift Question

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

Answer Source

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")
    }