1

I have got a observe function that shows added items to Firebase Realtime Database.

    func observerMessages(completion: @escaping (FireBaseResponse, MessageDataModel) -> Void) {
    let ref = Database.database().reference().child(FireBaseConstants.Database.messages).queryOrdered(byChild: FireBaseConstants.Database.timestamp).queryEnding(atValue: firstMessageTimestamp)
    ref.observe(.childAdded) { (snapshot) in
        if let dict = snapshot.value as? [String:Any] {
            if let username = dict["username"] as? String,
                let timestamp = dict["timestamp"] as? Int,
                let text = dict["text"] as? String,
                let senderId = dict["senderId"] as? String {
                let message = MessageData(username: username, timestamp: timestamp, text: text, senderId: senderId, messageId: snapshot.key)
                print("observeMessages")
                completion(.success, message)
            }
        }
    }
}

Problem is that this function triggers for all items that already in database. So it retrieves all data in this child. And I want it retrieve data, that added only after this function called.

  • That function will trigger once for each item in the database that fits the criteria (which allows you to populate a tableView datasource for example) and thereafter only for new children that are added. Just change your criteria to return children with a timestamp of after the current time the function is called. It will return no children immediately and only new children thereafter. – Jay Mar 03 '20 at 19:47

1 Answers1

1

Firebase synchronizes data at a specific location or for a specific query between the server and the client. There is no built-in API to ask for only new data to be sent.

There are a few ways to accomplish this use-case on top of the API:

  1. Only store the new data in a location, and remove it when the client has read it. This is a common way to implement message passing on Firebase: write a message queue for each client, and have the client delete data as it processes it.

  2. Only query for data that has been written since the client last read data. This requires that you have a createdAt or updatedAt timestamp property on each child node, and that you store the lastReadDataAt timestamp in the client. Now when the client connects, it runs a query that orders by the property, and passes in the timestamp of when it last synchronized. With these parameters the database will only return data that was created/updated since the last time the client read.

  3. Request only the one most recent item. This means that you order the data by some chronological key (such as the keys generated by childByAutoId) and then request only the one most recent child node from the database with limitQuery(toLast:1). With this, you only get the single most recent child node. While this works for some cases, I hardly ever use it because you run the chance of missing events that happen when the client loses its connection.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807