Bir NSDate'i NSUserDefaults'ta depolamanın en iyi yolu nedir?


174

Bir NSDate'i karşılaştığım NSUserDefaults'ta depolamanın iki yolu var.

Seçenek 1 - setObject: forKey:

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

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

Seçenek 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];

Lehte ve aleyhte olanlar

seçenek 1

Bu kompakt ve mantıklı görünüyor. Ancak, Date Formatter hataları nedeniyle bunun yanlış gitmesi konusunda endişelerim var .

seçenek 2

Bu beceriksiz görünüyor. Bunun doğruluğundan da emin değilim - yaptığım bir testte, Apple Docs'un NSTimeInterval'in "sonraki aşama doğruluğu" olduğunu söylemesine rağmen, tarihi geri aldığımda 48 saniye geçti.

Gereksinimler

Hangi yöntemi seçersem seçmeliyim:

  1. Bir saniye içinde hassas.

  2. Okunabilir ve güvenilir.

Benim sorum

Seçenek 2'deki yanlışlık yanlış bir şey yaptığım için mi?

Bu iki seçenekten hangisini kullanırsınız?

Farkında olmadığım başka bir seçenek var mı?

Teşekkürler!

Yanıtlar:


380

Gereksiz yere işleri karmaşıklaştırıyorsunuz. Tarihi neden bir zaman aralığına (sonra zaman aralığını farklı bir ilkeye dönüştürüyorsunuz)? Sadece [sharedDefaults setObject:theDate forKey:@"theDateKey"]ve onunla bitir. NSDate, PLIST biçimi (tarihler, sayılar, dizeler, veriler, sözlükler ve diziler) tarafından desteklenen "ana türlerden" biridir, böylece doğrudan depolayabilirsiniz.

Kanıt için belgelere bakın .

Tarihi doğrudan saklayın ve alın ve doğru şeyi yapın (saat dilimleri, hassasiyet vb. Dahil). Diğerlerinin söylediği gibi, hiçbir biçimlendirici yoktur.


8
Joshua, cevabın için teşekkürler. Aptal kıvrımlı şamandıra yaklaşımını denememin nedeni, başka bir büyük geliştiricinin bunu yaptığını gördüm ve bunu iyi bir nedenden dolayı yaptığını düşündüm. Belli ki değil. SetObject: forKey: kullanmak için kendi içgüdüme daha fazla güvenmeliydim ve bunu yaptım.
John Gallagher

7
Gereksiz komplikasyon düşüncesine karşı şiddetle şiddetliyim - geliştiriciler ve genellikle tembel insanlar için iyi bir özellik. :-)
Joshua Nozzi

Böyle bir yaklaşımın kullanıldığı durumlar çoğunlukla NSUserDefaults genel bir ara katman yazılımı için kullanıcı tercihlerinin bir depolama uygulaması olarak kullanıldığında ...
Coyote

@Coyote: Bu durumda hala NSUserDefaults aracılığıyla erişilir veya bir özellik listesi dosyasından ayrıştırılır, böylece aynı erişim veya ayrıştırma, gerektiği gibi dönüştürülebilen uygun bir NSDate nesnesi vermelidir.
Joshua Nozzi

3
@JohnGallagher [kenar çubuğu] Birisinin zayıf uygulaması için özel uygulamasını yanlış anlamayın . Orijinal düşünceniz "bunu iyi bir nedenden dolayı yaptığını düşündü ... Açıkçası değil", ancak söz konusu geliştiricinin gereksinimlerinin tüm kapsamını anladıysanız geçerli olabilir. Yaklaşımını "açıkça bu şekilde yapmak için iyi bir neden yok" olarak körü körüne etiketlemek küstah ve yakın fikirlidir. Bununla birlikte, evet, aksi takdirde yapmak için bir nedeniniz yoksa, Joshua'nın basit tutmaya yaklaşımını kabul ediyorum.
dooleyo

14

Seçenek # 1 için, bir tarih biçimlendiricisinin dahil olduğuna inanmıyorum. Muhtemelen kaputun altında, ama kırık olmadığını hayal ediyorum. Tarih ISO 8601 biçiminde saklanır .

Seçenek # 2 için, tabanlı sürümler yerine -setDouble:forKey:ve -doubleForKeykullanın float. Hassas hatalarınızın nedeni bu olabilir.


Vay canına, John. Çok hızlı cevabınız için teşekkürler. Kişisel olarak hangisini kullanırsınız?
John Gallagher

8
Tarihi, zaman aralığını değil, doğrudan kullanın. Bu kadar temel bir API'nin bu kadar çok uygulama güvendiğinde bozulduğundan şüpheliyim.
John Calsbeek

Mükemmel. Bu benim içgüdümdü, ancak üçüncü taraf kodunu şamandıra yöntemini kullanan saygın bir geliştirici tarafından görmüştüm, bu yüzden onu kullanmasının iyi bir nedeni olacağını düşündüm. Belli ki değil. Cevabınız için tekrar teşekkürler!
John Gallagher

1
Gördüğünüz kod, hangi türlerin doğrudan bir özellik listesinde saklanabileceğini hatırlamıyor olabilir.
John Calsbeek

2
Kayıt için - 32 bit şamandıraların doğruluk için sadece 24 biti vardır, bu nedenle 1970'den bugüne 40 yıl, 40 * 365 * 86400 saniye ve (40 * 365 * 86 400) / (2 ** 24) = 75 saniye hatası . Çift hassasiyet bir DateTime aralığıdır ve RAW hassasiyeti artık saniyenin milyonda birinden daha iyidir.
Tom Andersen

5

NSUserDefaults kullanın; tarihler Zulu saatinde saklanır, bu yüzden endişelenecek bir saat dilimi sorunu yoktur. Saat diliminizde saklayın, başka bir saat diliminde çekin, iyi olacaksınız, sistem dönüşümü ele alıyor (endişelenecek tarih biçimlendiricisi yok).


0

Son kullanma tarihini Facebook Graph API'sından kaydediyorsanız, * Option 2 * kullanacağım .

İkinci seçenek kolayca bir dizeye dönüştürülebilir (stringWithFormat kullanılarak). En önemlisi, Grafik API için çalışır.

Ayrıca, tarihinizin biçimi hakkında endişelenmenize gerek yoktur. NSDateFormatter ile uğraşmamak 48 saniyelik bir hata olasılığına değer.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.