我有一个聊天记录,最初在.observe( .childAdded)
中调用了我的viewDidLoad
侦听器,并在viewDidDisappear
中将其删除了,但是在阅读了此注释 from this question之后,我将侦听器移到了viewWillAppear
,现在无论何时切换视图并返回,侦听器将再次运行,并且我的tableData被两次填充相同的信息。
例如。说我在聊天中只有一个来自其他用户的消息,说“你好”。如果chat vc在tabTwo中,则vc第一次出现时,该代码将运行,并且collectionView的数据源将显示1条消息“ hello”。如果我按一个不同的选项卡并返回tabTwo,现在将有2条消息说“你好”(相同的确切消息),因为代码再次遍历了。如果有100条消息,这将成为一个严重的问题。这意味着将有200条消息,并且每次我切换标签并返回时它将不断增加。
我还应该在删除观察者时清除tableData并在viewDidDisappear中重新加载collectionView,这样在再次调用viewWillAppear时不会重复所有数据吗?这就是我为解决此问题所做的事情,但这似乎并不正确。
有没有更好的方法可以在viewDidLoad中调用观察者,然后在viewWillAppear中再次读取它,而不会导致我的collectionView复制数据?
let currentUserId = Auth.auth().currentUser?.uid!
let toId = "theOtherUsersId"
var tableData = [Message]()
let ref = Database.database().reference().child("messageIds")
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
ref.child(currentUserId).child(toId).observe( .childAdded, with: { [weak self] (snapshot) in
let messageId = snapshot.key
self?.getMessagesWith(messageId)
})
}
func getMessagesWith(_ messageId: String) {
Database.database().reference().child("messages").child(messageId).observeSingleEvent(of: .value, with: { [weak self] (snapshot) in
guard let dict = snapshot.value as? [String: Any] else { return }
let message = Message(dict: dict)
self?.tableData.append(message)
self?.collectionView.reloadData()
})
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
tableData.removeAll() // something seems wrong about doing this
collectionView.reloadData()
ref.removeAllObservers()
}
最佳答案
我原来的回答下的@GaloTorresSevilla评论是正确的。他建议将观察者移动到viewWillAppear并仅使用messageId过滤掉tableData中已经存在的任何消息。他是100%正确的,因为当我切换回标签页时,没有数据重复
let currentUserId = Auth.auth().currentUser?.uid!
let toId = "theOtherUsersId"
var tableData = [Message]()
let ref = Database.database().reference().child("messageIds")
override func viewDidLoad() {
super.viewDidLoad()
// nothing to do here
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
ref.child(currentUserId).child(toId).observe( .childAdded, with: { [weak self] (snapshot) in
let messageId = snapshot.key
// in viewWillAppear if the tableData contains the messageId above then return
if self.tableData.contains (where: { $0.messageId ?? “” == messageId }) {
return
}
self?.getMessagesWith(messageId)
})
}
func getMessagesWith(_ messageId: String) {
Database.database().reference().child("messages").child(messageId).observeSingleEvent(of: .value, with: { [weak self] (snapshot) in
guard let dict = snapshot.value as? [String: Any] else { return }
let message = Message(dict: dict)
self?.tableData.append(message)
self?.collectionView.reloadData()
})
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
ref.child(currentUserId).child(toId).removeAllObservers()
}
关于ios - Swift Firebase-如何将观察者添加到viewDidLoad中,如何在viewDidDisappear中将其删除,然后在viewWillAppear中再次读取它?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/55676592/