I am fetching some data from my Firebase Storage. The data arrives as a snapshot:
FirebaseDatabase.userMessagesReference?.child(contact.uid).queryOrderedByKey().queryEnding(atValue: lastMessage?.key ?? latestMessage?.key).queryLimited(toLast: 10).observeSingleEvent(of: .value, with: { (messageKeysSnapshot) in
while let childSnap = messageKeysSnapshot.children.nextObject() as? DataSnapshot {
print(childSnap)
}
}, withCancel: { (error) in
print(error.localizedDescription)
})
I'd like to get every child of the children array. Unfortunately, something seems to be wrong, it does not work as expected. Instead of returning every child within the while-loop, the first child is just returned infinite times (and there are at least 10 messages in the database).
Also, when checking the messageKeysSnapshot and printing it to the console (by setting a breakpoint, etc...), I can see that there are several children. I definitely think that there's something wrong with the children
enumerator.
How can I get every child once?
messageKeysSnapshot.children
returns an NSEnumerator
object that knows how to retrieve the objects one by one. The enumerator has its own state and keeps track of what it has given you. The idea is to get the enumerator once, and then call .nextObject()
on it repeatedly. The problem is that instead of getting the enumerator just once, you are getting a new copy each time through the loop, which explains why you are seeing the first item over and over again.
Instead, assign the enumerator to a let
and then reference it:
FirebaseDatabase.userMessagesReference?.child(contact.uid).queryOrderedByKey().queryEnding(atValue: lastMessage?.key ?? latestMessage?.key).queryLimited(toLast: 10).observeSingleEvent(of: .value, with: { (messageKeysSnapshot) in
let enumerator = messageKeysSnapshot.children
while let childSnap = enumerator.nextObject() as? DataSnapshot {
print(childSnap)
}
}, withCancel: { (error) in
print(error.localizedDescription)
})
Alternatively, you could use a for in
loop that works directly with enumerators and use case let
to make sure childSnap
is a DataSnapshot
:
FirebaseDatabase.userMessagesReference?.child(contact.uid).queryOrderedByKey().queryEnding(atValue: lastMessage?.key ?? latestMessage?.key).queryLimited(toLast: 10).observeSingleEvent(of: .value, with: { (messageKeysSnapshot) in
for case let childSnap as DataSnapshot in messageKeysSnapshot.children {
print(childSnap)
}
}, withCancel: { (error) in
print(error.localizedDescription)
})