【问题标题】:How to create negative Firebase timestamp in swift如何在 swift 中创建负 Firebase 时间戳
【发布时间】:2017-08-29 10:59:09
【问题描述】:

对于我正在开发的 iOS 应用程序,我需要按降序获取消息,即最新消息首先出现,然后是第二条最新消息,等等。

从查看其他 SO 答案和研究看来,我的情况的最佳方法是创建一个负时间戳,然后将其作为消息的额外属性保存到数据库中。

然后,我将使用 queryOrderedByChild('negativeTimestamp') 获取 observeSingleEvent 中的消息,然后让 childAdded 观察者处理初始调用后发送的消息。

在 firebase documentation 中,它说我可以从代码的这个 sn-p 中获取服务器时间戳值 firebase.database.ServerValue.TIMESTAMP

如何为 Swift 3 编写这个?

【问题讨论】:

  • 我很确定 refs 是由时间戳添加的,所以我认为甚至不需要任何排序
  • 也就是说,除非你正在做某种加入
  • 另一种解决方案是使用limitToLast,然后在客户端进行排序。例如。 messages.sort { $0.timestamp > $1.timestamp }
  • 它们是按升序排列的 - 我对 limitToLast 的问题是,当谁知道用户可能有多少未读消息时,您必须想出一个任意数字
  • 我想另一种解决方案可能是使用 observeSingleEvent 使用 .value 来计算有多少消息,然后使用 limitToLast 使用该数字进行初始提取

标签: ios swift firebase firebase-realtime-database


【解决方案1】:

首先,查看 cmets 中的链接答案。该答案依赖于客户端生成一个否定的时间戳并写入 Firebase。

如果您想让 Firebase 生成时间戳,也可以使用这个小巧的 Firebase 结构和一段代码来完成。

首先我们来看看结构

root
  parent_node
    -Y8j8a8jsjd0adas
       time_stamp: -1492030228007
  timestamp: 1492030228007

接下来,一些用于创建和使用该结构的代码:

定义一个我们可以在类中使用的 var,它引用 Firebase 时间戳

let kFirebaseServerValueTimestamp = [".sv":"timestamp"]

以及将观察者添加到时间戳节点的函数:

func attachObserver() {

    let timestampRef = self.ref.child("timestamp")
    let parentNodeRef = self.ref.child("parent_node")
    var count = 0

    timestampRef.observe(.value, with: { snapshot in

        if snapshot.exists() {
            count += 1
            if count > 1 {
                let ts = snapshot.value as! Int
                let neg_ts = -ts
                let childNodeRef = parentNodeRef.childByAutoId()
                let childRef = childNodeRef.child("time_stamp")
                childRef.setValue(neg_ts)
                count = 0
            }
        }
    })

还有一个写出时间戳的函数,从而导致观察者触发,它根据 Firebase 时间戳在 parent_node 内创建子节点

func doTimestamp() {
    let timestampRef = self.ref.child("timestamp")
    timestampRef.setValue(kFirebaseServerValueTimestamp)
}

这是纲要。

在 attachObserver 函数中,我们将观察者附加到时间戳节点 - 该节点可能存在也可能不存在,但如果不存在,它将被创建 - 继续阅读。每当时间戳节点中发生事件时,都会调用闭包中的代码。

当 doTimestamp 函数被调用时,它会创建一个时间戳并将其写入时间戳节点,然后触发我们在 attachObserver 中附加的观察者。

observe 闭包中的代码执行以下操作:

确保快照包含某些内容,如果包含,则增加一个计数器(稍后会详细介绍)。如果计数器大于 1,则从快照中获取时间戳作为整数。然后,创建它的负数并将其作为 parent_node 的子节点写回 Firebase。

这将如何应用,只要您想使用 Firebase 生成的时间戳为子节点添加时间戳,但反向加载/排序的值为负值 - 这说明了 OP 问题。

这里的问题是当这种情况发生时

    timestampRef.setValue(kFirebaseServerValueTimestamp)

它实际上向节点写入了两次,这将导致 close 中的代码被调用两次。

也许 Firebaser 可以解释这一点,但我们需要忽略第一个事件并捕获第二个事件,即实际时间戳。

所以第一个事件会导致观察者更接近触发,使 count = 1,由于 if 语句将被忽略。

然后触发第二个事件,其中包含实际的时间戳,这就是我们用来制作否定并写入 Firebase 的内容。

希望这对 OP 和评论者有所帮助。

【讨论】:

    【解决方案2】:

    不管是不是 Swift,另一个概念性的解决方案是依赖 Firebase 的服务器时间偏移值。

    它不如firebase.database.ServerValue.TIMESTAMP 精确,但差异通常在毫秒内。优点是它可以让您在客户端上创建一个负时间戳,而无需两次更新您的 Firebase 节点。

    您在需要时从 Firebase 获取服务器时间偏移值,在客户端生成负时间戳,然后将您的对象保存在 Firebase 中一次。

    见: https://groups.google.com/forum/#!topic/firebase-talk/EXMbZmyGWgE https://firebase.google.com/docs/database/ios/offline-capabilities#clock-skew(适用于 iOS)。 https://firebase.google.com/docs/database/web/offline-capabilities#clock-skew(网络版)。

    var offsetRef = firebase.database().ref(".info/serverTimeOffset");
    offsetRef.on("value", function(snap) {
      var offset = snap.val();
      var negativeTimestamp = (new Date().getTime() + offset) * -1;
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-05-11
      • 1970-01-01
      • 2021-02-25
      • 2018-08-16
      • 1970-01-01
      • 2021-07-20
      • 1970-01-01
      相关资源
      最近更新 更多