NSUserDefaultsにNSDateを保存する最適な方法は何ですか?


174

私が遭遇したNSUserDefaultsにNSDateを格納する方法は2つあります。

オプション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のバグのため、これがうまくいかないのではないかと心配しています。

オプション2

これは不器用であるようです。私はまた、その正確さについても確信がありません-私が行った1つのテストでは、日付を取得したとき、NSDocTimeIntervalには「1秒未満の正確さ」があるとApple Docsが言っていたにもかかわらず、48秒ずれていました。

必要条件

どの方法を選択しても、それは次のとおりでなければなりません。

  1. 1秒以内に正確に。

  2. 読みやすく信頼できる。

私の質問

私が何か間違っているので、オプション2は不正確ですか?

これらの2つのオプションのうち、どちらを使用しますか?

私が知らない別のオプションはありますか?

ありがとう!

回答:


380

あなたは不必要に物事を複雑にしています。日付を時間間隔に変換するのはなぜですか(時間間隔は別のプリミティブに変換されます)。ただ[sharedDefaults setObject:theDate forKey:@"theDateKey"]です。NSDateは、PLIST形式(日付、数値、文字列、データ、ディクショナリ、配列)でサポートされている「主な型」の1つなので、直接格納できます。

証明については、ドキュメントを参照してください。

日付を直接保存して取得し、それを確認する(タイムゾーン、精度などを含む)。他の人が言ったように、関与するフォーマッターはありません。


8
ジョシュア、あなたの答えをありがとう。私が愚かな複雑なフロートアプローチを試した理由は、別の優れた開発者がそれを行うのを見ただけで、彼が何らかの理由でそれをしたと思ったからです。明らかにそうではありません。setObject:forKey:を使用して、それを実行するという自分の本能にもっと自信を持つべきです。
John Gallagher

7
私は、不必要な複雑化という非常に考えられていること、つまり開発者や一般的に怠惰な人々にとっては良い特性に対して、非常に暴力的です。:-)
Joshua Nozzi 2010年

このようなアプローチが使用されるのは、ほとんどの場合、NSUserDefaultsが汎用ミドルウェアのユーザー設定のストレージ実装として使用される場合です...
Coyote

@Coyote:この場合、NSUserDefaultsを介してアクセスされているか、プロパティリストファイルから解析されているため、同じアクセスまたは解析によって、必要に応じて変換できる適切なNSDateオブジェクトが生成されます。
ジョシュアノッツィ

3
@JohnGallagher [サイドバー]誰かの特定の実装を悪いものと間違えないでください。「彼が何らかの正当な理由でそれをしたと思った...明らかにそうではなかった」というあなたの元の感情は、あなたがその開発者の要件の範囲全体を理解した場合にのみ有効である可能性があります。彼のアプローチを盲目的に「明らかにこの方法で行う正当な理由はない」とラベルを付けることは、ずば抜けて心のこもったことです。そうは言っても、そうしなければならない理由がなければ、私はそれをシンプルに保つためのジョシュアのアプローチに同意します。
dooleyo 2013

14

オプション#1の場合、日付フォーマッターが関係しているとは思いません。恐らくフードの下にありますが、壊れていないと思います。日付はISO 8601形式で保存されます。

オプション#2には-setDouble:forKey:-doubleForKeyは、- floatベースのバージョンの代わりにをます。それが精度エラーの原因である可能性があります。


うわー、ジョン。非常に迅速な回答をありがとうございます。個人的にどちらを使用しますか?
John Gallagher

8
時間間隔ではなく、日付を直接使用します。非常に多くのアプリがそれに依存している場合、そのような基本的なAPIが壊れているとは思えません。
John Calsbeek、2010年

優れた。それは私の本能でしたが、尊敬される開発者がfloatメソッドを使用するサードパーティのコードを見たので、彼がそれを使用したいくつかの正当な理由があると思いました。明らかにそうではありません。お返事ありがとうございます!
John Gallagher

1
あなたが見たそのコードは、開発者がプロ​​パティリストに直接格納できる型を覚えていなかった可能性があります。
John Calsbeek、2010年

2
レコードの場合-32ビットの浮動小数点数は精度のために24ビットしかないため、1970年から現在までは40年、つまり40 * 365 * 86400秒であり、(40 * 365 * 86 400)/(2 ** 24)= 75秒のエラー。倍精度は、DateTimeインターバルであり、そのRAW精度は100万分の1秒よりも優れています。
トムアンデルセン

5

NSUserDefaultsを使用します。日付はズールー時間で格納されるため、心配するタイムゾーンの問題はありません。それをあなたのタイムゾーンに保存し、別のタイムゾーンに引き出してください。問題はありません。システムが変換を処理します(日付フォーマッターは心配する必要はありません)。


0

FacebookグラフAPIから有効期限を保存する場合は、* オプション2 *を使用します。

オプション2は簡単に文字列に変換できます(stringWithFormatを使用)。最も重要なのは、グラフAPIで機能することです。

さらに、日付の形式について心配する必要はありません。NSDateFormatterを処理しないことは、48秒のエラーの可能性に値します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.