【问题标题】:What's the optimum way of storing an NSDate in NSUserDefaults?在 NSUserDefaults 中存储 NSDate 的最佳方式是什么?
【发布时间】:2011-01-02 02:24:03
【问题描述】:

我遇到过两种在 NSUserDefaults 中存储 NSDate 的方法。

选项 1 - setObject:forKey:

// Set
NSDate *myDate = [NSDate date];
[[NSUserDefaults standardUserDefaults] setObject:myDate forKey:@"myDateKey"];

// Get
NSDate *myDate = (NSDate *)[[NSUserDefaults standardUserDefaults] objectForKey:@"myDateKey"];

选项 2 - timeIntervalSince1970

// Set
NSDate *myDate = [NSDate date];
NSTimeInterval myDateTimeInterval = [myDate timeIntervalSince1970];
[[NSUserDefaults standardUserDefaults] setFloat:myDateTimeInterval forKey:@"myDateKey"];

// Get
NSTimeInterval myDateTimeInterval = [[NSUserDefaults standardUserDefaults] floatForKey:@"myDateKey"];
NSDate *myDate = [NSDate dateWithTimeIntervalSince1970:myDateTimeInterval];

优点和缺点

选项 1

这似乎是紧凑和合乎逻辑的。但是,由于Date Formatter bugs,我担心这会出错。

选项 2

这似乎很笨拙。我也不确定它的准确性——在我做的一项测试中,当我检索到日期时,它已经过了 48 秒,尽管 Apple Docs 说 NSTimeInterval 具有“亚秒级精度”。

要求

无论我选择哪种方法,都必须是:

  1. 精确到一秒钟。

  2. 可读且可靠。

我的问题

选项 2 不准确是因为我做错了什么吗?

您会使用这两个选项中的哪一个?

还有其他我不知道的选项吗?

谢谢!

【问题讨论】:

    标签: cocoa datetime nsdate nsuserdefaults nstimeinterval


    【解决方案1】:

    您不必要地使事情复杂化。为什么要将日期转换为时间间隔(然后将时间间隔转换为不同的原语)?只需[sharedDefaults setObject:theDate forKey:@"theDateKey"] 就可以了。 NSDate 是 PLIST 格式(日期、数字、字符串、数据、字典和数组)支持的“主要类型”之一,因此您可以直接存储它。

    请参阅the documentation 以获取证据。

    只需直接存储和检索日期并观察它做正确的事(包括时区、精度等)。正如其他人所说,没有涉及格式化程序。

    【讨论】:

    • 约书亚,感谢您的回答。我尝试愚蠢的复杂浮动方法的原因仅仅是因为我看到另一个伟大的开发人员这样做,我认为他这样做是有充分理由的。显然不是。我应该对自己的直觉更有信心,那就是使用 setObject:forKey: 并且已经完成了。
    • 我对不必要的复杂化的想法非常强烈 - 对于开发人员和一般懒惰的人来说这是一个很好的特征。 :-)
    • 使用这种方法的情况主要是当 NSUserDefaults 被用作通用中间件的用户偏好的存储实现时......
    • @Coyote:在这种情况下,它仍然通过 NSUserDefaults 访问或从属性列表文件中解析,因此相同的访问或解析应该产生一个适当的 NSDate 对象,可以根据需要进行转换。跨度>
    • @JohnGallagher [sidebar] 不要将某人的具体实现误认为是糟糕的实现。您最初的观点“认为他出于某种充分的理由这样做......显然不是”只有在您了解所述开发人员要求的整个范围时才有效。盲目地将他的做法贴上“显然没有充分理由这样做”的标签是自以为是且心胸狭窄。话虽如此,是的,如果您没有理由不这样做,我会同意 Joshua 保持简单的方法。
    【解决方案2】:

    对于选项 #1,我认为不涉及日期格式化程序。可能在引擎盖下,但我想它没有坏。日期以ISO 8601 形式存储。

    对于选项#2,使用-setDouble:forKey:-doubleForKey 而不是基于float 的版本。这可能是您的精度错误的原因。

    【讨论】:

    • 哇,约翰。感谢您非常迅速的答复。您个人会使用哪个?
    • 直接使用日期,而不是时间间隔。当这么多应用程序依赖它时,我怀疑这样一个基本的 API 会被破坏。
    • 优秀。那是我的直觉,但我看过一位受人尊敬的开发人员使用 float 方法编写的第三方代码,所以我认为他使用它是有充分理由的。显然不是。再次感谢您的回答!
    • 您看到的代码可能是开发人员不记得哪些类型可以直接存储在属性列表中。
    • 记录一下——32位浮点数只有24位精度,所以1970年到现在是40年,也就是40*365*86400秒,(40 * 365 * 86 400) / ( 2 ** 24) = 75 秒错误。双精度是 DateTime 间隔,它的 RAW 精度现在优于百万分之一秒。
    【解决方案3】:

    使用 NSUserDefaults;日期以祖鲁时间存储,因此无需担心时区问题。将其存储在您的时区,将其拉出到另一个时区,您会没事的,系统会处理转换(无需担心日期格式化程序)。

    【讨论】:

      【解决方案4】:

      如果您从 Facebook Graph API 保存到期日期,我会使用 *选项 2*

      选项二可以很容易地转换为字符串(使用 stringWithFormat)。最重要的是,它适用于 Graph API。

      另外,您不必担心日期的格式。不处理 NSDateFormatter 可能会出现 48 秒的错误。

      【讨论】:

        猜你喜欢
        • 2012-08-18
        • 2013-06-14
        • 1970-01-01
        • 1970-01-01
        • 2016-09-13
        • 2014-06-29
        • 2021-10-22
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多