如何在swift中创建负Firebase时间戳

时间:2017-04-04 09:56:10

标签: ios swift firebase firebase-realtime-database

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

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

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

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

如何为Swift 3写这个?

2 个答案:

答案 0 :(得分:3)

首先,请在评论中查看链接的答案。该答案依赖于客户端生成时间戳,该时间戳为负并写入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)

它实际上会向节点写入两次,这会导致更接近的代码被调用两次。

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

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

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

希望这有助于OP和评论者。

答案 1 :(得分: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;
});