Reputation: 665
i want to get all messages by their creation date (which is timestamp).
My data structure looks like this:
messages
XRJONcahNUgeNrfkH3cmITJt3409 (auto uid of owner - user)
-KoOSxA2Iajk3kv20U_p (automatic uid generated by Firebase)
message: "Hi"
senderId: "X8Oxg5J9Imb12C1iYBXJT9P48909"
senderName: "Dave"
timestamp: 1505813320526 (automatic timestamp)
-GdOSxR2Iajk3kv20U_p --- I NEED TO SORT THESE UIDS
message: "Hello"
senderId: "G7Oxg5J9Imb12C1iYBXJT9P48909"
senderName: "Frank"
timestamp: 1505813321024 (automatic timestamp)
And I get all messages like this:
database.child("messages").child(ownersId).observeSingleEvent(of: .value, with: { (snapshot) in
print(snapshot)
if let messagesDict = snapshot.value as? [String:AnyObject] {
for (_,message) in messagesDict {
self.messages.append((message["message"] as? String)!)
self.users.append((message["senderName"] as? String)!)
self.timestamps.append((message["timestamp"] as? IntMax)!)
}
}
completionHandler(true)
}) { (error) in
print(error.localizedDescription)
completionHandler(false)
}
So the question is, how can I get all messages ordered from the oldest to the newest? I dont know how can I use ordering methods (queryOrderedByKey(), queryOrderedByValue() or queryOrdered(byChild: "timestamp") in this specific case. Firebase sends me data in random order (I dont know if it is random, but it is not sorted by date).
Upvotes: 1
Views: 2392
Reputation: 38833
You use database.queryOrdered
instead of database.child
like this:
database.queryOrdered(byChild: "messages"). observeSingleEvent(.value, with: { (snapshot) in
print("\(snapshot.value)")
}
But you could also get the data as you have done today and then sort the list self.timestamps
instead:
self.timestamps.sorted(by: { $0 > $1 })
Update:
Create a model and append your properties to that model and then append to a list and sort that list after that. Like this:
struct Model {
let message: String?
let senderId: String?
let senderName: String?
let timestamp: IntMax
init(message: String?, senderId: String?, senderName: String?, timestamp: IntMax?) {
self.message = message
self.senderId = senderId
self.senderName = senderName
self.timestamp = timestamp
}
}
var models = [Model]()
models.sorted(by: { $0.0.timestamp > $0.1.timestamp })
Update 2:
To add the models checkout the code example below:
database.child("messages").child(ownersId).observeSingleEvent(of: .value, with: { (snapshot) in
print(snapshot)
var models = [Model]()
if let messagesDict = snapshot.value as? [String:AnyObject] {
for (_,message) in messagesDict {
if let message = message["message"] as? String, let senderName = message["senderName"] as? String, let timestamp = message["timestamp"] as? IntMax, let senderId = message["senderId"] as? String {
let model = Model(message: message, senderId: senderId, senderName: senderName, timestamp: timestamp)
models.append(model)
}
}
models.sorted(by: { $0.0.timestamp > $0.1.timestamp })
}
completionHandler(true)
}) { (error) in
print(error.localizedDescription)
completionHandler(false)
}
Upvotes: 2
Reputation: 598797
As Rashwan said, you'll need to call queryOrderedByChild()
to get the items returns in the correct order. Then you loop over snapshot.children
to ensure you also process them in the correct order.
So:
database.child("messages").queryOrdered(byChild: "timestamp").observe(.value, with: { snapshot in
for child in snapshot.children.allObjects as! [DataSnapshot] {
print("\(child.key)")
}
completionHandler(true)
})
The important thing inside the callback is to not convert the entire snapshot into a dictionary, because the dictionary won't maintain the order of the items.
Upvotes: 3