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
}
}
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()}
}