代码之家  ›  专栏  ›  技术社区  ›  Parth

在可能发生变化的起始值处启动firebase查询触发器,以便在swift中有效获取该点之后的数据

  •  0
  • Parth  · 技术社区  · 5 年前

    编辑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
    

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

    speech drill db structure 1 speech drill db structure 2

    另一种方法可能包括两个查询。然后,当视图消失时,第一个查询的执行可能会停止。但我不知道该怎么做 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 也有并发症,所以我没有走这条路。)

    0 回复  |  直到 5 年前
        1
  •  0
  •   usergio2    5 年前

    对于这个问题,我想不出什么解决办法。我不确定你在Firebase上的数据结构如何。我想你会有一份 messages 和 user 节点。

    如果你的目标是统计未读邮件。

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

    你的节点应该像这样

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

    另外,关于您的查询,为什么在使用UserDefaults时它不起作用,很可能是因为数据类型不匹配。你在储藏东西 Date 这是一个正在尝试检索的对象 double 价值

    如果你计划使用最后一次阅读的信息时间戳,我觉得它不会像上面那样有效地调整你存储或计算未读信息总量的方式。

        2
  •  0
  •   ossamacpp    5 年前

    我在启用离线持久性时也遇到过类似的问题

    数据库数据库()。isPersistenceEnabled=true

    尝试通过将此行更改为禁用它

    数据库数据库()。isPersistenceEnabled=false

    推荐文章