首页 > 解决方案 > 何时在 tableView 单元中分离 firebase 侦听器?

问题描述

在聊天应用程序中,为了跟踪参与聊天的每个用户的每个聊天的最后一条消息和未读消息,当 tableView 单元出列时,我在.childChanged单元上附加了一个侦听器。当监听器被触发时,我会更新每一行的聊天 label.text 以进行相应的聊天。
我应该什么时候删除这些听众,或者在我的情况下更新单元格中的聊天的最佳做法是什么?

程序的流程是什么?
1. 下载当前用户
2. 下载当前用户 chatID
3. 下载每个 chatID 的聊天
4. 用聊天填充 tableView
5. 在每个单元格中观察 childChanged 在
chats/chat.chatUID/currentUserUID/.observe(.childChanged)
6. 如果“ unreadMessagesCount”已更改,在单元格上更新它

class ChatTableViewCell: UITableViewCell {
  @IBOutlet weak var lastMessageLabel: UILabel!

    var chat: Chat! {
       didSet{
        self.updateUI()
     }
  }

  func updateUI() {

    self.chat.observeChildChanged(chat: self.chat, currentUserUID:user.userUID) { (lastMessage, unreadMessagesCount) in

        if !lastMessage.isEmpty{
            self.lastMessageLabel.text = lastMessage
        }

        if unreadMessagesCount > 0 {
            self.lastMessageLabel.font = UIFont.boldSystemFont(ofSize: 16.0)
            self.chatUnreadMessagesCount.text = "\(unreadMessagesCount)"
        } else {
            self.lastMessageLabel.font = UIFont.systemFont(ofSize: 15.0)
            self.chatUnreadMessagesCount.text = ""
        }
    }
  }
} 

 class MessagesViewController: UITableViewController {
     override func viewDidLoad() {
      //observe ~/users/uid
       DDatabaseRReference.users(uid: uid).reference().observeSingleEvent(of: .value, with: { (snapshot) in

        guard snapshot.exists() else {return}

            if let userDict = snapshot.value as? [String : Any] {
                self.currentUser = UserModel(dictionary: userDict)
                self.userWasDownloaded = true //this will trigger the setter and start downloading chatId's of current user
            }
    })
 }

 var userWasDownloaded: Bool {
     get {
        return true
     }
     set {
        self.fetchChatsIdsOf(currentUser: self.currentUser)
        self.tableView.reloadData()
     }
 }


func fetchChatsIdsOf(currentUser: UserModel) {
     //get chatIds of currentUser from ~/users/currentUser.userUID/chatIds
    DDatabaseRReference.users(uid: currentUser.userUID).reference().child("chatIds").observe(.childAdded, with: { (snapshot) in

        let chatUID = snapshot.key
        if !self.chatIdsDownloaded.contains(chatUID) {
            self.chatIdsDownloaded.append(chatUID)
        }
    })
}

//after chatIdsDownloaded is set,
//download the new chat for the last chat appended to chatIdsDownloaded array
var chatIdsDownloaded = [String]() {
    didSet {
        guard let chatID = chatIdsDownloaded.last else  {return}
        self.downloadNewChat(chatID: chatID)
    }
}

    func downloadNewChat(chatID: String) {
   DDatabaseRReference.chats.reference().child(chatID).observeSingleEvent(of: .value, with: { (snapshot) in
        ......
      self.currentUserChats.insert(chatChecked, at: 0)
     }
   }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCell(withIdentifier: "ChatTableViewCell", for: indexPath) as! ChatTableViewCell
       cell.chat = currentUserChats[indexPath.row]
      return cell
    }
 } 



chats    // <- all chats in the app for all users in the app
 -LOMVtcjOEOu2p1apMKV
   chatUID: "-LOMVtcjOEOu2p1apMKV"
   isGroupChat: true
   lastMessage: "Katherine Gregory has joined the group"
   lastUpdate: 1539761870.2237191
   +users
     IN4pgCS5NqQZZLpdmoz1KeDiFqj2
     fcmToken: ""
     firstName: "Alex"
     userUID: "IN4pgCS5NqQZZLpdmoz1KeDiFqj2"
     unreadMessagesCount: 5



users   // <- all users in the app
 IN4pgCS5NqQZZLpdmoz1KeDiFqj2
   +chatIds
      -LOMVtcjOEOu2p1apMKV: true
      - name: ""
      - email: ""
       ...etc

标签: swiftfirebasefirebase-realtime-database

解决方案


您可以检查是否为单元添加了 2 个或更多观察者。

在此处添加断点或 print():

self.chat.observeChildChanged(chat: self.chat, currentUserUID: user.userUID) { (lastMessage, unreadMessagesCount) in {
   //breakpoint or print("observeChildChanged")
   ...
}

请重复使用你的手机。
发送新消息。

如果您有 2 条或更多消息,则意味着您没有只设置一个观察者。

也许这种方法并不完美,但它可以帮助你(在添加新的之前删除旧的观察者):

var chat: Chat! {
   didSet {
      self.removeOldObserver()
      self.updateUI()
   }
}

func removeOldObserver() {
   ...
}

推荐阅读