Le *_*ced 5 nsdate grand-central-dispatch ios swift
"Walltime"是Grand Central Dispatch使用的一种鲜为人知的时间格式.Apple在这里谈到它:
https://developer.apple.com/library/ios/documentation/Performance/Reference/GCD_libdispatch_Ref/
但是有一些东西真的很方便,但它是一个粘性的检票口.很难让它与其他时间格式一起玩得很好,这就是我的问题所在.
我可以通过将a NSDate转换为a 来进行壁挂timespec,然后使用dispatch_walltime:
let now = NSDate().timeIntervalSince1970
let nowWholeSecsFloor = floor(now)
let nowNanosOnly = now - nowWholeSecsFloor
let nowNanosFloor = floor(nowNanosOnly * Double(NSEC_PER_SEC))
var thisStruct = timespec(tv_sec: Int(nowWholeSecsFloor),
tv_nsec: Int(nowNanosFloor))
let wallTime = dispatch_walltime(& thisStruct, 0)
Run Code Online (Sandbox Code Playgroud)
但是主爱一只鸭子,我无法弄清楚如何让它重新变成一只鸭子NSDate.这是我的尝试:
public func toNSDate(wallTime: dispatch_time_t)->NSDate {
let wallTimeAsSeconds = Double(wallTime) / Double(NSEC_PER_SEC)
let date = NSDate(timeIntervalSince1970: wallTimeAsSeconds)
return date
}
Run Code Online (Sandbox Code Playgroud)
结果NSDate不只是关闭,而是有点滑稽,如五百年或其他什么.正如Martin R所指出的那样,问题在于它dispatch_time_t是一个不透明的值,没有时间表示.
有谁知道如何做到这一点?
编辑:如果创建壁挂时间的过程令人困惑,这基本上是正在发生的事情:
NSDate使用a定义时间,Double小数点后的所有内容都是纳秒.dispatch_time,可以创建一个walltime,定义时间UInt64,所以你必须在它之间进行转换Double和UInt64使用它.要进行这种转换,您需要使用a timespec,它需要秒和纳秒作为单独的参数,每个参数必须是Int.
一个完整的转换'继续!
Mar*_*n R 12
真正的答案是:你做不到.
在"time.h"头文件中声明:
/*!
* @typedef dispatch_time_t
*
* @abstract
* A somewhat abstract representation of time; where zero means "now" and
* DISPATCH_TIME_FOREVER means "infinity" and every value in between is an
* opaque encoding.
*/
typedef uint64_t dispatch_time_t;
Run Code Online (Sandbox Code Playgroud)
因此,dispatch_time_t使用未记录的"抽象"时间表示,甚至可能在发布之间进行更改.
话虽这么说,让我们有一些乐趣,并试图找出dispatch_time_t真正的东西.所以我们看看"time.c",其中包含以下内容的实现
dispatch_walltime():
dispatch_time_t
dispatch_walltime(const struct timespec *inval, int64_t delta)
{
int64_t nsec;
if (inval) {
nsec = inval->tv_sec * 1000000000ll + inval->tv_nsec;
} else {
nsec = (int64_t)_dispatch_get_nanoseconds();
}
nsec += delta;
if (nsec <= 1) {
// -1 is special == DISPATCH_TIME_FOREVER == forever
return delta >= 0 ? DISPATCH_TIME_FOREVER : (dispatch_time_t)-2ll;
}
return (dispatch_time_t)-nsec;
}
Run Code Online (Sandbox Code Playgroud)
有趣的部分是最后一行:它取纳秒的负值,并将此值转换回(无符号)dispatch_time_t.还有一些特殊情况.
因此,扭转转换,我们要否定的
dispatch_time_t,并采取为纳秒:
public func toNSDate(wallTime: dispatch_time_t)->NSDate {
// Tricky part HERE:
let nanoSeconds = -Int64(bitPattern: wallTime)
// Remaining part as in your question:
let wallTimeAsSeconds = Double(nanoSeconds) / Double(NSEC_PER_SEC)
let date = NSDate(timeIntervalSince1970: wallTimeAsSeconds)
return date
}
Run Code Online (Sandbox Code Playgroud)
事实上,这会将walltime正确地转换回原始版本
NSDate,至少在我在OS X应用程序中测试它时.
但是再说一遍:不要这样做!您将依赖于未记录的表示形式,该表示形式可能会在OS版本之间发生变化 可能还存在上述代码中未考虑的特殊情况.iOS运行时中的表示也可能不同,我没试过. 你被警告了!