gpt4 book ai didi

ios - 在可能更改的起始值处启动 firebase 查询触发器,以便在该点之后 swift 有效地获取数据

转载 作者:行者123 更新时间:2023-12-05 06:52:07 26 4
gpt4 key购买 nike

编辑2

这是我目前的设置。当侧面导航 View 隐藏时,我将移除观察者,并在它出现时重新启动它。如果用户默认值会在 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 等。这甚至在我打开聊天 View 和最后一个读取消息时间戳在查询中更新。我知道上次读取的消息时间戳正在更新,因为控制台输出如下所示:

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

我的数据库结构对于好奇的人来说是这样的:

speech drill db structure 1 speech drill db structure 2

执行此操作的另一种方法可能涉及包含 2 个查询。然后,当 View 消失时,可以停止第一个查询的执行。但我不知道如何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仅针对新添加的消息而不是删除的消息触发 .childAdded 事件。在这里,我有一种强烈的感觉,每当添加或删除子项时,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 中。我们是否可以将该值用作 queryStarting(atValue:)(因为我希望它会像 NSDate().timeIntervalSince1970 那样返回一个新值)。这里的问题是上次读取的消息时间戳和消息数量都可能发生变化。因此,如果我在其中一个上创建一个观察者,那么它将导致在另一端加载不必要的数据。有人可以向我解释为什么查询按预期使用 NSDate().timeIntervalSince1970 而不是 UserDefaults 吗?以及如何以最佳方式解决未读消息计数问题。

(我想到的一种方法涉及在用户默认值上添加 KVO。但我看到 that process 也有复杂性,所以我没有走那条路。)

最佳答案

对于这个问题,我能想到的解决方案很少。我不确定您在 Firebase 上的数据结构如何。我假设您将有一个 messagesuser 节点的列表。

如果您的目标是统计未读消息。

您可以尝试改变您的方法。当您从 .childAdded 收到新消息时,您可能希望将其存储到相应的 user 节点中,并在触发对特定消息的读取操作时将其删除。这种方式效率更高,尤其是当您稍后收到更大的消息时。或者不添加新节点,只更新 user 节点中 totalUnreadMessage 的值

你的节点应该看起来像这样

root
|
- users
|
- 0
|
- totalUnreadMessage : 10 << update this when there is new message for this user

另外关于您的查询,为什么当您使用 UserDefaults 时它不起作用,很可能是因为数据类型不匹配。例如:您正在存储作为对象的 Date 并尝试检索 double 值。

如果您打算使用上次阅读的消息时间戳,我觉得它不如调整您存储或计算未读消息总数的方式那样有效。

关于ios - 在可能更改的起始值处启动 firebase 查询触发器,以便在该点之后 swift 有效地获取数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66015549/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com