Mohamed Elloumi Mohamed Elloumi - 1 month ago 11
Swift Question

Getting only first object from Firebase Snapshot Swift

So this is my Firebase Structure:

enter image description here

I'm trying to get all books pictures (bookImage), add them to list and then use this list to fill a table or anythings else. (I'm using swift 3)

struct item {
let picture: String!}

var items = [item]()
func getLatestAddedItems(){
let databaseRef = FIRDatabase.database().reference()
databaseRef.child("Items").observe(.childAdded, with: {
FIRDataSnapshot in
let picture = (FIRDataSnapshot.value as? NSDictionary)?["bookImage"] as? String ?? ""
//self.items.insert(item(picture: picture), at: 0)
self.items.append(item(picture: picture))
print(self.items[0].picture)
print(self.items[1].picture) // error here
})}


I'm able to see the first print output but on the second one I'm getting fatal error: Index out of range even I have 3 books on my database.

Answer

Since your using .childAdded, it iterates through that closure for each object in the data tree, in this case, each book. When you try to print the second picture, its still in its first iteration. Meaning you only have retrieved the first book so far. That's why you can print the first book item but not the second one. If you moved the print statements outside of the closure, and then did the print statements after the closure iterated over all three books, you wouldn't get the error.

Don't change it to .value unless if every time a new one is subsequently added you want to get the entire list of books all over again. If its a large amount of books, it will be a lot of data to go through each time.

Summary: .childAdded gives you one book at a time, with a new snapshot for each one. .value gives you all the books in one snapshot, then you must iterate over them yourself in the closure. ex.

for snap in snapshot.children {
// now you can do something with each individual item
}  

also I just noticed your using the FIRDataSnapshot type in your closure, that should be a variable which represents the snapshot you received, not the type itself. Change "FIRDataSnapshot in" to something like "snapshot in" snapshot is a representation of what information was given to you by the observe closure, in this case, an object with a type of FIRDataSnapshot.