Duplicated rows in array populated by Firebase

Viewed 31

I have a chatApp but for some reason, whenever a user send a message inside a room, the conversation row (displaying the last msg sent and the username who sent it) duplicate with 2 row showing the same last message and 1 row showing an older message (the one before the last one). To solve this i added a refresh function which is clearing the array and reloading the tableView but it's not practical. I don't know how to prevent this. Here's my code:

RoomViewController

var lastDocumentSnapshot: DocumentSnapshot!
var currentPage = 1
private var rooms = [Room]()

@objc func refresh() {
        self.rooms.removeAll()           
        self.tableView.reloadData()
    }
 @objc func fetchRooms() {
        var query: Query!

       tableView.refreshControl?.beginRefreshing()
       
        if rooms.isEmpty {
            query = COLLECTION_ROOMS.order(by: "timestamp", descending: false).limit(toLast: 10)
             print("First 10 room loaded")
         } else {
             query = COLLECTION_ROOMS.order(by: "timestamp", descending: false).end(beforeDocument: lastDocumentSnapshot).limit(toLast: 10)
            print("Next 10 room loaded")
            self.currentPage = self.currentPage + 1
         }
       query.addSnapshotListener { (snapshot, err) in
           if let err = err {
               print("\(err.localizedDescription)")
           } else if snapshot!.isEmpty {
               self.tableView.refreshControl?.endRefreshing()
               return
           }
           guard let lastSnap = snapshot?.documents.first else {return}
           self.lastDocumentSnapshot = lastSnap
           
           snapshot?.documentChanges.forEach({ (change) in
               let dictionary = change.document.data()
               let message = RoomMessage(dictionary: dictionary)
               let ownerID = dictionary["ownerID"] as? String ?? ""
               
               UserService.fetchUser(withUid: ownerID) { user in
                   let conversation = Room(user: user, recentMessage: message)
                   self.rooms.append(conversation)
                   self.rooms.sort(by: { $0.recentMessage.timeStamp.compare($1.recentMessage.timeStamp) == .orderedDescending })
                   self.tableView.reloadData()
               }
            })
               self.tableView.refreshControl?.endRefreshing()
               self.lastDocumentSnapshot = snapshot?.documents.first
       }
    }
1 Answers

I managed to solve the issue by adding a listener and stop listening whenever a msg is sent inside a chat.

var listener: [ListenerRegistration] = []
var isListening = false

@objc func fetchRooms() {
       print("Fetching Room")

        var query: Query!
        self.isListening = true

       tableView.refreshControl?.beginRefreshing()
       
        if rooms.isEmpty {
           query = COLLECTION_ROOMS.order(by: "timestamp", descending: false).limit(toLast: 10)
             print("First 10 room loaded")
         } else {
            query = COLLECTION_ROOMS.order(by: "timestamp", descending: false).end(beforeDocument: lastDocumentSnapshot).limit(toLast: 5)
            print("Next 10 room loaded")
         }
       let listener = query.addSnapshotListener { (snapshot, err) in
           if err != nil {
//                       print("\(error.localizedDescription)")
                   } else if snapshot!.isEmpty {
                       self.tableView.refreshControl?.endRefreshing()
                       return
                   }
           guard let lastSnap = snapshot?.documents.first else {return}
           self.lastDocumentSnapshot = lastSnap
           
           snapshot?.documentChanges.forEach({ (change) in
               if change.type == .added {
                   let dictionary = change.document.data()
                   self.rooms.append(Room(dictionary: dictionary))
                   self.rooms.sort(by: { $0.timeStamp.compare($1.timeStamp) == .orderedDescending })
                   self.tableView.reloadData()
               }
               if change.type == .modified {
                   self.isListening = false
               }
               if change.type == .removed {
               }
           })
               self.tableView.refreshControl?.endRefreshing()
               self.lastDocumentSnapshot = snapshot?.documents.first
       }
       if isListening == false { listener.remove()}
    }
Related