如何对Firebase数据库进行分页? [英] How paginate with Firebase Database?

查看:57
本文介绍了如何对Firebase数据库进行分页?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试查询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.

  1. 从firebase下载的消息以升序到达,因此我必须下载所有5个messageID,将它们分配给名为arrayOfMessageID的临时数组,然后遍历每个id和self.observeOnce(messageId: messageID). 在使用这种方法之前,在每个已下载的messageID之后,我都会调用self.observeOnce(messageId: messageID),以这种方式,我无法在将消息分配给message或jsqMessages之前对其进行排序.或者可能有,但不是一个整洁的.
  1. 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 and self.observeOnce(messageId: messageID) for each messageID.
    Prior to this approach, after each downloaded messageID, I was calling self.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数据库进行分页?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆