not able retrieve documents in chat application according to the timestamp

假如想象 提交于 2020-01-25 10:15:09

问题


I am using the below code to retrieve the messages in a chat application according to the timestamp but it is not retrieving in order of the timestamp, How should I make sure that messages retrieved are in the order of the timestamp.

I am using Firestore database and Swift IOS for this application

below is the code parts

timestamp saved in database

    let timestamp = Int(NSDate().timeIntervalSince1970) 

Code to retrieve messages

   let ref = Firestore.firestore().collection("messages").order(by: "timestamp", descending: true)

            ref.addSnapshotListener { (snapshot, error) in
                snapshot?.documentChanges.forEach({ (diff) in

                    let messageId = diff.document.documentID
                    let messageRef = Firestore.firestore().collection("messages")
                        .document(messageId)


                    messageRef.getDocument(completion: { (document, error) in
                        guard let dictionary = document?.data() as? [String : Any] else { return }

                        let message = Message(dictionary: dictionary)

                        print("we fetched this message \(message.text)")


                            self.messages.append(message)

                            DispatchQueue.main.async {
                                self.collectionView.reloadData()
                                let indexPath = IndexPath(item: self.messages.count - 1, section: 0)
                                self.collectionView.scrollToItem(at: indexPath, at: .bottom, animated: true)
                            }

                    })
                })
            }

回答1:


Perhaps an oversight but what's happening here is the code gets the data you want in descending order by timestamp, but then gets that same data again, which will be unordereed because it's being retrieved asynchronously, and adds to the array.

                   func doubleGettingData() {
                      let ref = Firestore.firestore()....
Gets data ->          ref.addSnapshotListener { (snapshot, error) in
                         snapshot?.documentChanges.forEach({ (diff) in
Gets data again ->          messageRef.getDocument(completion

To add a bit more context, the 'outside' function shown in the question is in fact getting the documents in the correct order. However, getting those same documents again, they are being returned from Firebase in whatever order they complete in because Firebase calls are asynchronous. This can be proven if we remove all the code except for the two calls. Here's an example Firestore Structure

message_0:
   timestamp: 2
message_1
   timestamp: 0
message_2
   timestamp: 1

and when some print statement are added, here's what's happening

outside func gets: message_0 //timestamp 2
outside func gets: message_2 //timestamp 1
outside func gets: message_1 //timestamp 0
   inside func returns: message_1 //timestamp 0
   inside func returns: message_2 //timestamp 1
   inside func returns: message_0 //timestamp 2

I would make a couple of changes...

Here's my Message class and the array to store the messages in

class Message {
    var text = ""
    var timestamp = ""
    convenience init(withSnap: QueryDocumentSnapshot) {
        self.init()
        self.text = withSnap.get("text") as? String ?? "No message"
        self.timestamp = withSnap.get("timestamp") as? String ?? "No Timestamp"
    }
}
var messages = [Message]()

and then the code to read the messages, descending by timestamp and store them in the array. Note

The first query snapshot contains added events for all existing documents that match the query

func readMessages() {
    let ref = Firestore.firestore().collection("messages").order(by: "timestamp", descending: true)
    ref.addSnapshotListener { querySnapshot, error in
        guard let snapshot = querySnapshot else {
            print("Error fetching snapshots: \(error!)")
            return
        }

        snapshot.documentChanges.forEach { diff in
            if (diff.type == .added) {
                let snap = diff.document
                let aMessage = Message(withSnap: snap)
                self.messages.append(aMessage)
            }
            if (diff.type == .modified) {
                let docId = diff.document.documentID
                //update the message with this documentID in the array
            }
            if (diff.type == .removed) {
                let docId = diff.document.documentID
                //remove the message with this documentID from the array
            }
        }
    }
}

This code will also watch for changes and deletions in messages and pass that event to your app when they occur.



来源:https://stackoverflow.com/questions/59017647/not-able-retrieve-documents-in-chat-application-according-to-the-timestamp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!