我正在尝试查询Firebase数据库,以便在JSQMessagesViewController中加载更多消息。初始化viewDidLoad后,我使用childAdded进行查询并获取最新的5条消息。
此后,我在didTapLoadEarlierMessagesButton
中调用prepareToObserveOnce
方法。其目的是观察一个类型为value的事件,并获得比早先下载的消息还旧的5条消息。
问题在于,调用prepareToObserveOnce
时,消息将插入到数组的末尾,而不是开始。
当在print(" self.arrayOfItems is \( self.arrayOfItems)")
中调用observeChildAddedMessages
时,它会打印["11", "12", "13", "14", "15"]
,但是当我调用observeOnce(messageId: String)
时,它会显示["11", "12", "13", "14", "15", "6", "7", "8", "9", "10"]
。我的逻辑往南走。
-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
答案 0 :(得分:0)
有两个问题。
1.是我将新消息附加到数组,而不是将它们插入索引0。
arrayOfMessageID
的临时数组,然后遍历该数组并为每个messageID遍历self.observeOnce(messageId: messageID)
。 br />
在使用这种方法之前,在每个下载的messageID之后,我都在调用self.observeOnce(messageId: messageID)
,这样,在将消息分配给message或jsqMessages之前,我将无法对消息进行排序。或者可能有,但不是整洁的。 我的课程
`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