I am trying to query firebase database in order to load more messages in a JSQMessagesViewController. When viewDidLoad is initialized, I make a query using childAdded and get the most recent 5 messages.
Thereafter, in didTapLoadEarlierMessagesButton
I call prepareToObserveOnce
method. Its purpose is to observe a single event of type value and get 5 more messages which are older than the ones that were downloaded earlier.
The problem is that when prepareToObserveOnce
is called, the messages are inserted at the end of the array, rather than at the beginning.
When print(" self.arrayOfItems is \( self.arrayOfItems)")
is called in observeChildAddedMessages
it prints ["11", "12", "13", "14", "15"]
, but when I call observeOnce(messageId: String)
, it prints ["11", "12", "13", "14", "15", "6", "7", "8", "9", "10"]
. Somewhere my logic went south.
-messages
-LKQdzoSTGqjSWu78t7R
messageUID:"-LKQdzoSTGqjSWu78t7R"
senderUID: "UfGFsZ57jEdXyrtRzEZ1i3wOBZJ2"
type: "text"
-chats
-LKQduebP-TEGM95kE5N
chatUID: "-LKQduebP-TEGM95kE5N"
lastMessage: "15"
-messageIds
-LKQeAJFMi5fvrdv4Xl6: "-LKQdzoSTGqjSWu78t7R"
My class
class ChatVC: JSQMessagesViewController {
var oldestKey: String! //keeps track of the oldest key of the oldest message download
var firstMessagesLoaded: Bool = false //enables us to assign the oldest key of the message downloaded once all messages have been downloaded in observeChildAddedMessages method
var arrayOfItems = String() // for test purposes
var chatSelected: Chat! //chat received from MessagesViewController
var currentUser: UserModel!
var messages = [Message]()
var jsqMessages = [JSQMessage]()
override func viewDidLoad() {
super.viewDidLoad()
//when view first loads, this method is called and will download the most recent 5 messages sent in chat
self.observeChildAddedMessages()
}
override func collectionView(_ collectionView: JSQMessagesCollectionView!, header headerView: JSQMessagesLoadEarlierHeaderView!, didTapLoadEarlierMessagesButton sender: UIButton!) {
//when the headerView is touched, this method should download 5 more messages earlier than oldestKey
self.prepareToObserveOnce()
}
}//end of class
extension ChatVC {
//read the messages from the chat (if any) when viewDidLoad is initialized
func observeChildAddedMessages() {
// ~/chats/childByAutoId/messageIds
let chatMessageIdsRef = chatSelected.chatRef.child("messageIds")
chatMessageIdsRef.queryOrderedByKey().queryLimited(toLast: 5).observe(.childAdded, with: { (snapshot) in
let messageId = snapshot.value as! String
let messageKey = snapshot.key
if self.firstMessagesLoaded == false {
self.oldestKey = messageKey
self.firstMessagesLoaded = true
}
// ~/messages/messageId
let messagesRef = DDatabaseRReference.messages.reference()
messagesRef.child(messageId).observeSingleEvent(of: .value, with: { (snapshot) in
let message = Message(dictionary: snapshot.value as! [String : Any])
if !self.messages.contains(message) {
let jsqMessage = JSQMessage(senderId: message.senderUID, displayName: message.senderDisplayName, text: message.text)
self.messages.append(message)
self.jsqMessages.append(jsqMessage!)
print(" self.arrayOfItems is \( self.arrayOfItems)")
self.finishReceivingMessage()
}
})//end of messagesRef.child(messageId).observeSingleEvent
})//end of chatMessageIdsRef.queryOrderedByKey()
}//end of observeChildAddedMessages
}//end extension
extension ChatVC {
func prepareToObserveOnce() {
// ~/chats/childByAutoId/messageIds
let chatMessageIdsRef = chatSelected.chatRef.child("messageIds")
if oldestKey == nil {
chatMessageIdsRef.queryOrderedByKey().queryLimited(toLast: 5).observeSingleEvent(of: .value, with: { snapshot in
guard snapshot.exists() else {return}
let firstItem = snapshot.children.allObjects.first as! DataSnapshot
self.oldestKey = firstItem.key
for item in snapshot.children.allObjects as! [DataSnapshot] {
let messageId = item.value as! String
self.observeOnce(messageId: messageId)
}
})
} else {
//get 5 more elements relative to oldestKey, meaning that we get the oldestKey inclusive. - .queryEnding(atValue: oldestKey)
//These are earlier messages than currentKey
chatMessageIdsRef.queryOrderedByKey().queryEnding(atValue: oldestKey).queryLimited(toLast: 6).observeSingleEvent(of: .value, with: { snapshot in
guard snapshot.exists() else {return}
let firstItem = snapshot.children.allObjects.first as! DataSnapshot
for item in snapshot.children.allObjects as! [DataSnapshot] {
let messageId = item.value as! String
//avoid getting same message twice by checking the key of the message downloaded != currentKey
if firstItem.key != self.oldestKey {
self.observeOnce(messageId: messageId)
}
}
})
}
}//end prepareToObserveOnce
}//end extension
extension ChatVC {
func observeOnce(messageId: String) {
// ~/messages/messageId
let messagesRef = DDatabaseRReference.messages.reference()
messagesRef.child(messageId).observeSingleEvent(of: .value, with: { (snapshot) in
let message = Message(dictionary: snapshot.value as! [String : Any])
if !self.messages.contains(message) {
let jsqMessage = JSQMessage(senderId: message.senderUID, displayName: message.senderDisplayName, text: message.text)
self.messages.append(message)
self.jsqMessages.append(jsqMessage!)
print(" self.arrayOfItems is \( self.arrayOfItems)")
}
})
}//end of observeOnce
}//end of extension