编辑2
这是我目前的设置。当侧导航视图隐藏时,我正在移除观察者,当它出现时,我将重新启动观察者。如果用户默认值将在
queryStarting(atValue: defaults.double(forKey: lastReadMessageTimestampKey) + 0.000001)
喜欢
timeIntervalSince1970
在其他地方的类似查询中:
queryStarting(atValue: NSDate().timeIntervalSince1970)
.
class SideNavigationController: UIViewController {
...
var unreadMessageCountUpdateQueryHandle: DatabaseHandle?
...
override func viewWillAppear(_ animated: Bool) {
logger.info("SideNavigationControllers view will appear")
updateUnreadMessagesCount()
super.viewWillAppear(true)
...
}
override func viewWillDisappear(_ animated: Bool) {
logger.info("SideNavigationControllers view will disapear")
stopUpdatingUnreadMessagesCount()
super.viewWillDisappear(animated)
...
}
func updateUnreadMessagesCount() {
logger.info("Updating count of unread messages")
let messageTimestampKey = DiscussionMessage.CodingKeys.messageTimestamp.stringValue
let defaults = UserDefaults.standard
unreadMessageCountUpdateQueryHandle = messagesReference.queryOrdered(byChild: messageTimestampKey).queryStarting(atValue: defaults.double(forKey: lastReadMessageTimestampKey) + 0.000001).observe(.value) { (snapshot) in
if let value = snapshot.value as? [String: Any] {
print("Number of unread messages: \(value.count) Last Read TS \(UserDefaults.standard.double(forKey: lastReadMessageTimestampKey))")
self.menuItems[1].itemName = "Discussions (\(value.count))"
self.sideNavTableView.reloadData()
} else {
self.menuItems[1].itemName = "Discussions"
self.sideNavTableView.reloadData()
}
}
}
func stopUpdatingUnreadMessagesCount() {
guard let handle = unreadMessageCountUpdateQueryHandle else { return }
messagesReference.removeObserver(withHandle: handle)
}
编辑:
添加
.synchronize()
保存默认值后也没有帮助。
我还对查询进行了一些调整,从上次读取的消息的时间戳的偏移量开始,这样在计算未读消息时就不会包括它。
现在查询如下所示:
let discussionMessageTimestampKey = DiscussionMessage.CodingKeys.messageTimestamp.stringValue
messagesReference.queryOrdered(byChild: discussionMessageTimestampKey)
.queryStarting(atValue: UserDefaults.standard.double(forKey: lastReadMessageTimestampKey) + 0.000001)
.observe(.value) { (snapshot) in
if let value = snapshot.value as? [String: Any] {
print("Number of unread messages: \(value.count) Last Read TS \(UserDefaults.standard.double(forKey: lastReadMessageTimestampKey))")
}
}
通过此查询,最初未读邮件数为
0
然后随着新消息的出现,它变成了1、2、3等等。这甚至是在我打开聊天视图并在查询中更新最后一次读取消息的时间戳之后。我知道上一次读取的消息时间戳正在更新,因为控制台输出如下所示:
Number of unread messages: 1 Last Read TS TS_OF_SECOND_LAST_MESSAGE
Number of unread messages: 2 Last Read TS TS_OF_SECOND_LAST_MESSAGE
Number of unread messages: 3 Last Read TS TS_OF_SECOND_LAST_MESSAGE
对于好奇的人来说,我的数据库结构是这样的:
另一种方法可能包括两个查询。然后,当视图消失时,第一个查询的执行可能会停止。但我不知道该怎么做
stop a query execution
找不到任何相关文件。
let messageTimestampKey = DiscussionMessage.CodingKeys.messageTimestamp.stringValue
let defaults = UserDefaults.standard
let query = messagesReference.observe(.childAdded) { (snapshot) in
if snapshot.exists() {
let startTimestamp = defaults.double(forKey: lastReadMessageTimestampKey)
let offset: Double = 0.00000001
messagesReference.queryOrdered(byChild: messageTimestampKey).queryStarting(atValue: startTimestamp + offset).observe(.value) { (snapshot) in
if let value = snapshot.value as? [String: Any] {
print("Number of unread messages: \(value.count) Last Read TS \(UserDefaults.standard.double(forKey: lastReadMessageTimestampKey))")
}
}
}
}
我正在创建一个聊天应用程序,我想计算未读消息的数量。最后读取的时间戳的值保存在我的实时数据库中的某个位置,每条消息都附有一个时间戳。最后读取的消息的时间戳也存储在用户默认值中。所以我试着用这个值
queryStarting(atValue:)
.但它并没有像预期的那样发挥作用。即使在默认值更新之后,查询仍然使用旧值,未读消息计数也会随之增加
.value
事件具有
.childAdded
事件中,即使添加了新消息,我也会得到一个常量(总是不正确)。
let discussionMessageTimestampKey = DiscussionMessage.CodingKeys.messageTimestamp.stringValue
messagesReference.queryOrdered(byChild: discussionMessageTimestampKey).queryStarting(atValue: UserDefaults.standard.double(forKey: lastReadMessageTimestampKey)).observe(.value) { (snapshot) in
if let value = snapshot.value as? [String: Any] {
print("Number of unread messages: \(value.count) Last Read TS \(UserDefaults.standard.double(forKey: lastReadMessageTimestampKey))")
}
}
我用的是
similar query
解雇
蔡尔德补充道
事件仅适用于新添加的邮件,不适用于已删除的邮件。在这里我有一种强烈的感觉
NSDate().timeIntervalSince1970
无论何时添加或删除子项,都会不断返回新值。即使在创建查询后添加了4条消息,并删除了其中1条,也不会触发此事件。正如Frank所解释的那样
here
.
let discussionMessageTimestampKey = DiscussionMessage.CodingKeys.messageTimestamp.stringValue
messagesReference.queryOrdered(byChild: discussionMessageTimestampKey).queryStarting(atValue: NSDate().timeIntervalSince1970).observe(.childAdded) {
(snapshot) in
...
}
这就引出了我的问题。由于用户默认查询不起作用,最后读取的消息时间戳也存储在firebase中。我们可以用这个值作为
查询启动(atValue:)
相反(我希望它会返回一个新的值,比如
NSDate()。1970年以来的时间间隔
是的)。这里的问题是,最后一次读取的消息时间戳和消息的数量都可能发生变化。因此,如果我在其中一个上创建一个观察者,那么它将导致在另一端加载不必要的数据。有人能给我解释一下为什么这个查询在
NSDate()。1970年以来的时间间隔
但不是和
UserDefaults
? 以及我如何解决最佳计算未读邮件数量的问题。
(我想到的一种方法是在用户默认设置上添加KVO
that process
也有并发症,所以我没有走这条路。)