如何从Firebase的iOS API获取服务器时间戳?

17

我有一个使用Firebase的iOS应用程序,目前有一些字典,其键是NSDate对象。显而易见的问题是NSDate从设备的系统时间获取,这并不是普遍适用的时间。

因此,使用Firebase的iOS API,最好的方法是什么来获取服务器时间戳(类似于Web API的Firebase.ServerValue.TIMESTAMP),以便我可以按时间顺序对我的字典键进行排序?

我也知道childByAutoID生成的ID具有时间顺序性,但我无法找到正确的方法在代码中对它们进行排序。虽然它们可能按时间顺序返回,但如果在它们上面调用类似于allKeys的函数时,顺序就会被打乱。

非常感谢任何关于此问题的帮助!


发现了这个小工具 - https://github.com/freak4pc/NSDate-ServerDate - 但如果 Firebase 有解决方案的话,那就更好了。 - Alex Costantini
4个回答

33

更新:在Firebase 3.0+ Swift中,您可以使用FIRServerValue.timestamp()。在Objective-C中,这是[FIRServerValue timestamp]

在Swift中,您现在可以使用Firebase 2.0.3+(3.0之前)的FirebaseServerValue.timestamp()

iOS中Firebase.ServerValue.TIMESTAMP的等效物是kFirebaseServerValueTimestamp。目前,这仅适用于Objective-C而不是Swift。

在Swift中,您可以创建自己的全局时间戳。

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

然后你就可以像使用其他内容一样使用kFirebaseServerValueTimestamp

但是你只能将其用作节点的值或优先级。你不能将其设置为键名(虽然我认为在Web API中也做不到)。

通常,在字典上调用allKeys不能保证顺序。

但是,如果您在节点上使用childByAutoID,则可以通过按字典顺序排序的NSArray返回来获取正确的顺序。类似这样的方法可以起作用:

[ref observeEventType:FEventTypeValue withBlock:^(FDataSnapshot *snapshot) {
    NSDictionary *value = snapshot.value;
    NSLog(@"Unsorted allKeys: %@", value.allKeys);
    NSArray *sortedAllKeys = [value.allKeys sortedArrayUsingSelector:@selector(compare:)];
    NSLog(@"Sorted allKeys: %@", sortedArray);
}];

这类似于按字母顺序对 NSArray 进行排序,但在对自动生成的 ID 进行排序时,您不希望进行本地化或大小写不敏感的排序,因此使用 compare: 而不是 localizedCaseInsensitiveCompare:


5

注意:看起来时间戳是在您的对象在Firebase中持久化之后添加的。这意味着,如果您在对象持久化的位置上设置了一个.Value事件监听器,它将被触发两次。一次是为了将初始对象存储在该位置,另一次是为了添加时间戳。我为此问题苦苦挣扎了好几天 :(

对于任何无法弄清为什么他们的事件侦听器会触发两次/多次的人来说,这是有用的信息!


3
从Firebase 4.0开始,您可以使用ServerValue.timestamp()。
例如:
    let ref = Database.database().reference().child("userExample")
    let values = ["fullName": "Joe Bloggs", "timestamp": ServerValue.timestamp()] as [String : Any]

    ref.updateChildValues(values) { (err, ref) in

        if let err = err {
            print("failed to upload user data", err)
            return
        }

    }

1
这很好,但是否有一种方法可以直接从服务器检索时间戳值以在updateChildalues完成块中使用? - lozflan

2
你可以使用FIRServerValue.timestamp()获取时间戳。
但是由于FIRServerValue.timestamp()监听器会被调用两次,监听器会被调用两次。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接