ios - Swift Firebase - 如何向 viewDidLoad 添加观察者,在 viewDidDisappear 中将其删除,然后在 viewWillAppear 中再次读取?
问题描述
我有一个聊天日志,最初我让我的.observe( .childAdded)
听众调用viewDidLoad
并将其删除,viewDidDisappear
但是在阅读了这个问题的评论后,我将听众移到了现在,每当我切换视图并返回时,听众都会重新运行并且我的 tableData 被填满两次获得相同的信息。 viewWillAppear
例如。假设我在聊天中只有 1 条来自其他用户说“你好”的消息。如果聊天 vc 在 tabTwo 中,则 vc 第一次出现时代码将运行,并且 collectionView 的数据源将有 1 条消息说“你好”。如果我按下不同的选项卡并返回 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()
}
推荐阅读
- sql - SQL - where 子句中的连接字符串未按预期工作 - Redshift
- javascript - 如何使用模板文字传递动态参数?
- java - Spring-boot with spring secutiry 错误:出现意外错误(类型=禁止,状态=403)
- python - python程序在不使用排序功能的情况下按升序对列表进行排序
- c# - 是否可以遍历模块中的变量?
- python - 如何将一个分支的提交(例如 rebase)添加到另外两个主要分支上?
- node.js - 从 MongoDB 中的数组中获取条件匹配元素的计数
- javascript - 页面加载自动选择下拉框选项
- r - 在 geom_bar 的列上方添加百分比,并带有分面
- xamarin.ios - 如何在 Twilio Video Room connect + CallKit iOS 13 之前断开通话