问题描述
我正在尝试查询Firebase数据库,以便在JSQMessagesViewController中加载更多消息.初始化viewDidLoad时,我使用childAdded进行查询并获取最新的5条消息.
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.
此后,在didTapLoadEarlierMessagesButton
中,我调用prepareToObserveOnce
方法.其目的是观察一个类型为value的事件,并获得比早先下载的消息还旧的5条消息.
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.
问题在于,当调用prepareToObserveOnce
时,消息将插入到数组的末尾,而不是开始.
当在observeChildAddedMessages
中调用print(" self.arrayOfItems is \( self.arrayOfItems)")
时,它会显示["11", "12", "13", "14", "15"]
,但是当我调用observeOnce(messageId: String)
时,它会显示["11", "12", "13", "14", "15", "6", "7", "8", "9", "10"]
.我的逻辑往南走.
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"
我的课程
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
推荐答案
有2个问题.
1.是我将新消息附加到数组,而不是将它们插入索引0.
There were 2 problems.
1. was that I was appending the new messages to the array rather than inserting them at index 0.
- 从firebase下载的消息以升序到达,因此我必须下载所有5个messageID,将它们分配给名为
arrayOfMessageID
的临时数组,然后遍历每个id和self.observeOnce(messageId: messageID)
.在使用这种方法之前,在每个已下载的messageID之后,我都会调用self.observeOnce(messageId: messageID)
,以这种方式,我无法在将消息分配给message或jsqMessages之前对其进行排序.或者可能有,但不是一个整洁的.
- The messages downloaded from firebase arrive in ascending order, thus I had to download all 5 messageID's , assign them to a temporary array named
arrayOfMessageID
and thereafter loop through it andself.observeOnce(messageId: messageID)
for each messageID.
Prior to this approach, after each downloaded messageID, I was callingself.observeOnce(messageId: messageID)
and in this way I would have had no way of ordering the messages prior to assigning them to messages or jsqMessages. Or there could have been, but not a neat one.
我的课程
`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)
//we can safely append messages here in .childAdded, because this method is called when viewDidLoad is initialized, so there are no other items in the array.
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
//create an array of messageID in order to reverse the messages as they arrive in ascending order and we can nor append neither insert at a specific index because they would appear like [10,9,8,7]
var arrayOfMessageID = [String]()
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 {
arrayOfMessageID.append(messageId)
}
}
arrayOfMessageID.reverse()
for messageID in arrayOfMessageID {
self.observeOnce(messageId: messageID)
}
//after downloading the messages is complete, set oldestKey as the firstItem downloaded. Remember, the download is done from low to high based on key timeStamp based, which means the firstItem downloaded is the oldest
self.oldestKey = firstItem.key
})
}
}//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.insert(message, at: 0)
self.jsqMessages.insert(jsqMessage!, at: 0)
//DO NOT append! Wrong way
self.messages.append(message)
self.jsqMessages.append(jsqMessage!)
print(" self.arrayOfItems is \( self.arrayOfItems)")
}
})
}//end of observeOnce
}//end of extension
这篇关于如何对Firebase数据库进行分页?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!