ios - Firebase 观察被调用两次?

标签 ios swift firebase firebase-realtime-database

我有一个聊天 View Controller 和一个聊天列表

每当我单击聊天列表上的对话时,我都会计算子级的总数并保存聊天大小(消息数)。

但是,观察者函数似乎被调用了两次,弄乱了我的真实聊天大小。

let messagesChannelRef = mainChannelRef.child(channelid).child("messages")
messagesChannelRef.observe(FIRDataEventType.value, with: { (snapshot: FIRDataSnapshot) -> Void in

   UserDefaults.standard.set(snapshot.childrenCount, forKey: "latestreadchatsize@\(channelid)")
   UserDefaults.standard.synchronize()

})

如何避免观察函数被调用两次?

更新的问题:

这是我使用的代码..

class ChannelListTableViewController: UITableViewController {
...........
...........

private lazy var channelRef: FIRDatabaseReference = FIRDatabase.database().reference().child("channels")

..........

func showChatDialog(channelObj: Channel){
        let navChatVc: UINavigationController = self.storyboard?.instantiateViewController(withIdentifier: "navChatView") as! UINavigationController
        let chatVc : ChatViewController = navChatVc.viewControllers.first as! ChatViewController
        chatVc.senderDisplayName = senderDisplayName
        chatVc.channel = channelObj
        chatVc.channelRef = channelRef.child(channelObj.id)

        let channelid = channelObj.id
        let messagesChannelRef = channelRef.child(channelid).child("messages")

        self.present(navChatVc, animated:true, completion: { () -> Void in

        let channelid = channelObj.id
            channelRef.child(channelid).child("messages").observe(FIRDataEventType.value, with: { (snapshot: FIRDataSnapshot) -> Void in

                UserDefaults.standard.set(snapshot.childrenCount, forKey: "latestreadchatsize@\(channelid)")
                UserDefaults.standard.synchronize()

            })
        })
}

...........
...........

} //end of class

每当单击 showChatDialog 时,它实际上会调用一次,但是当我从另一个客户端发送聊天消息时,观察函数会被调用两次?

我知道聊天客户端会互相调用新消息。因此,当 Firebase 用新消息更新时,我猜它会重新调用观察函数,这意味着它会监听任何更新?

最佳答案

解决方案已更新

最后,通过两种可能的方式找到了答案

  1. 观察单一类型

  2. 或者删除 FIRDatabaseHandle 观察者

//查看单个 channel 的消息总大小

//you can choose one of these 2 ways
let mainChannelRef: FIRDatabaseReference = FIRDatabase.database().reference().child("channels")

//1st way
if let channelid = channel?.id {
    mainChannelRef.child(channelid).child("messages").observeSingleEvent(of: .value, with: { (snapshot) in
        UserDefaults.standard.set(snapshot.childrenCount, forKey: "latestreadchatsize@\(channelid)")
        UserDefaults.standard.synchronize()
    })
}


//2nd way
if let channelid = channel?.id {
    let newRefHandle: FIRDatabaseHandle  = mainChannelRef.child(channelid).child("messages").observe(FIRDataEventType.value, with: { ( snapshot: FIRDataSnapshot) -> Void in
            UserDefaults.standard.set(snapshot.childrenCount, forKey: "latestreadchatsize@\(channelid)")
            UserDefaults.standard.synchronize()
    })
    mainChannelRef.child(channelid).child("messages").removeObserver(withHandle: newRefHandle)
}

两者都确保观察者仅被点击一次

关于ios - Firebase 观察被调用两次?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41047002/

相关文章:

ios - 如何将 imageData 保存到 NSManagedObject 属性

ios - 启用 Bitcode 的 Apple APP Store 上的移动应用程序大小

java - 如何将用户引导至其特定 Activity ?

javascript - 未收到 iOS 推送通知(Firebase 云功能)

android - java.util.HashMap 无法转换为 com.google.android.gms.maps.model.LatLng

ios - Cordova - iOS 上的 Zip 文件和文件夹

ios - UICollectionViewCell 相对于 CollectionView 的自动布局大小

swift - 如何在 TableView 上居中弹出窗口?

swift - 如何防止 future 的开发人员滥用 `switch` `default` 子句?

ios - 显示 Segue 后导航栏与我的内容重叠