Snapshot listener duplicating data

Hello, I'm working on this chat app and I have a snapshot listener to keep track the number of messages (with a badge) each user receives. I'm using a table view with pagination. The problem I'm having that I can't figure out is when a user gets a message, the table view duplicates the user, increases the badge number every time a message is received. Then, if i open the messages and then i go back to the first VC, there is another duplicate of the user but with no badge number because it was cleared. Any help is greatly appreciated.

VC

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
     
    fetchMatches()
  }

func fetchMatches() {
    fetchInfo { matches in
      self.match = matches
      self.matchedMessagesTV.reloadData()
    }
  }
   
  func fetchInfo(completion: @escaping([Match]) -> Void) {
    if lastDocument == nil {
      let query = MATCH_INFO_COLLECTION.document(currentUID!)
        .collection("info").order(by: MATCH_TIMESTAMP, descending: false)
      query.limit(to: 10).addSnapshotListener { (snapshot, error) in
         
        guard let last = snapshot?.documents.last else { return }
        guard let snap = snapshot else { return }
        snap.documentChanges.forEach({ diff in
           
          let dictionary = diff.document.data()
          let memberId = dictionary[DOCUMENT_ID] as? String ?? ""
          let memberAge = dictionary[AGE] as? Int ?? 0
          let memberName = dictionary[FIRST_NAME] as? String ?? ""
          let memberImageUrl = dictionary[PROFILE_IMAGE_URL] as? String ?? ""
          let memberCurrentCity = dictionary[CURRENT_CITY] as? String ?? ""
          let matchTimestamp = dictionary[MATCH_TIMESTAMP] as? Double ?? 0.0
          let messageCounter = dictionary[MESSAGE_COUNTER] as? Int ?? 0
           
          let matches = Match(memberId: memberId, memberAge: memberAge ,memberName: memberName, memberImageUrl: memberImageUrl, memberCurrentCity: memberCurrentCity, matchTimestamp: Date(timeIntervalSince1970: matchTimestamp), messageCounter: messageCounter)
           
          self.match.append(matches)
          self.memberId = matches.memberId
          self.lastDocument = last
          completion(self.match)
        })
      }
    } else {
      matchedMessagesTV.tableFooterView = createSpinnerFooter()
      let query = MATCH_INFO_COLLECTION.document(currentUID!)
        .collection("info").order(by: MATCH_TIMESTAMP, descending: false)
       
      DispatchQueue.main.async {
        self.matchedMessagesTV.tableFooterView = nil
      }
      query.start(afterDocument: self.lastDocument!)
        .limit(to: 10).addSnapshotListener { (snapshot, error) in
           
          guard let last = snapshot?.documents.last else { return }
          guard let snap = snapshot else { return }
          snap.documentChanges.forEach({ diff in
             
            let dictionary = diff.document.data()
            let memberId = dictionary[DOCUMENT_ID] as? String ?? ""
            let memberAge = dictionary[AGE] as? Int ?? 0
            let memberName = dictionary[FIRST_NAME] as? String ?? ""
            let memberImageUrl = dictionary[PROFILE_IMAGE_URL] as? String ?? ""
            let memberCurrentCity = dictionary[CURRENT_CITY] as? String ?? ""
            let matchTimestamp = dictionary[MATCH_TIMESTAMP] as? Double ?? 0.0
            let messageCounter = dictionary[MESSAGE_COUNTER] as? Int ?? 0
             
            let matches = Match(memberId: memberId, memberAge: memberAge ,memberName: memberName, memberImageUrl: memberImageUrl, memberCurrentCity: memberCurrentCity, matchTimestamp: Date(timeIntervalSince1970: matchTimestamp), messageCounter: messageCounter)
             
            self.match.append(matches)
            self.memberId = matches.memberId
            self.lastDocument = last
            completion(self.match)
             
          })
        }}
  }
class Match {
   
  var memberId: String
  let memberAge: Int
  let memberName: String
  let memberImageUrl: String
  let memberCurrentCity: String
  let matchTimestamp: Date!
  let messageCounter: Int
   
  init(memberId: String, memberAge: Int, memberName: String, memberImageUrl: String, memberCurrentCity: String, matchTimestamp: Date, messageCounter: Int) {
     
    self.memberId = memberId
    self.memberAge = memberAge
    self.memberName = memberName
    self.memberImageUrl = memberImageUrl
    self.memberCurrentCity = memberCurrentCity
    self.matchTimestamp = matchTimestamp
    self.messageCounter = messageCounter
  }
}

  • Can you tell us what is snapshot? I cannot find a method named addSnapshotListener in the Apple's frameworks.

  • My apologies, thats part of the Firebase Framework, but, basically my issue is when a field is updated tableView.reloadData() repeats the cell many times.

  • Thanks for clarifying. I have never worked with Firebase, so I am not sure, but your issue may be caused by the behavior of Firebase snapshot. You would get better responses sooner if you visit a site where more experienced developers of Firebase are watching.

Add a Comment