วิธีที่ดีที่สุดในการจัดเก็บ NSDate ใน NSUserDefaults คืออะไร


174

มีสองวิธีในการจัดเก็บ NSDate ใน NSUserDefaults ที่ฉันเจอ

ตัวเลือกที่ 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

ดูเหมือนว่าจะกะทัดรัดและมีเหตุผล แต่ฉันมีความกังวลเกี่ยวกับเรื่องนี้ผิดไปเพราะวันโรคจิตฟอร์แมต

ตัวเลือก 2

ดูเหมือนว่าจะเงอะงะ ฉันยังไม่แน่ใจเกี่ยวกับความถูกต้องของมัน - ในการทดสอบหนึ่งครั้งเมื่อฉันดึงวันที่กลับมาได้ภายใน 48 วินาทีแม้ว่า Apple Docs จะบอกว่า NSTimeInterval มี "ความแม่นยำย่อย"

ความต้องการ

วิธีใดก็ตามที่ฉันเลือกจะต้องเป็น:

  1. แม่นยำภายในไม่กี่วินาที

  2. อ่านและเชื่อถือได้

คำถามของฉัน

ตัวเลือกที่ 2 ไม่ถูกต้องเพราะฉันทำอะไรผิดหรือเปล่า?

คุณจะใช้ตัวเลือกใดในสองข้อนี้

มีตัวเลือกอื่นที่ฉันไม่ทราบหรือไม่?

ขอบคุณ!

คำตอบ:


380

คุณกำลังทำสิ่งที่ซับซ้อนโดยไม่จำเป็น เหตุใดคุณจึงแปลงวันที่เป็นช่วงเวลา (จากนั้นช่วงเวลาเป็นช่วงเวลาดั้งเดิม) เพียง[sharedDefaults setObject:theDate forKey:@"theDateKey"]และจะทำกับมัน NSDate เป็นหนึ่งใน "ประเภทหลัก" ที่สนับสนุนโดยรูปแบบ PLIST (วันที่, ตัวเลข, สตริง, ข้อมูล, พจนานุกรมและอาร์เรย์) ดังนั้นคุณสามารถจัดเก็บได้โดยตรง

ดูเอกสารประกอบการพิสูจน์

เพียงแค่จัดเก็บและเรียกคืนวันที่โดยตรงและดูมันทำสิ่งที่ถูกต้อง (รวมถึงโซนเวลาความแม่นยำ ฯลฯ ) ไม่มีการจัดรูปแบบที่เกี่ยวข้องดังที่คนอื่น ๆ พูด


8
โจชัวขอบคุณสำหรับคำตอบของคุณ เหตุผลที่ฉันลองใช้วิธีทุ่นที่ซับซ้อนอย่างโง่เง่าก็เพราะฉันได้เห็นนักพัฒนาที่ยอดเยี่ยมคนอื่นทำและฉันคิดว่าเขาทำไปด้วยเหตุผลที่ดี เห็นได้ชัดว่าไม่ ฉันควรมีความมั่นใจมากขึ้นในสัญชาตญาณของตัวเองซึ่งต้องใช้ setObject: forKey: และทำไปแล้ว
John Gallagher

7
ฉันมีความรุนแรงทันทีต่อความคิดที่ซับซ้อนมาก - เป็นนิสัยที่ดีสำหรับนักพัฒนาและคนขี้เกียจ :-)
Joshua Nozzi

กรณีที่ใช้วิธีการดังกล่าวเป็นส่วนใหญ่เมื่อใช้ NSUserDefaults เป็นการดำเนินการจัดเก็บข้อมูลของการตั้งค่าผู้ใช้สำหรับมิดเดิลแวร์ทั่วไป ...
Coyote

@Coyote: ในกรณีที่มันยังคงถูกเข้าถึงผ่าน NSUserDefaults หรือแยกวิเคราะห์จากไฟล์รายการคุณสมบัติดังนั้นการเข้าถึงหรือการแยกวิเคราะห์เดียวกันควรให้วัตถุ NSDate ที่เหมาะสมซึ่งสามารถแปลงได้ตามต้องการ
Joshua Nozzi

3
@JohnGallagher [แถบด้านข้าง]อย่าเข้าใจผิดว่ามีการใช้งานเฉพาะของคนยากจน ความรู้สึกดั้งเดิมของคุณ "คิดว่าเขาทำไปด้วยเหตุผลที่ดีบางอย่าง ... เห็นได้ชัดว่า" อาจไม่ถูกต้องเฉพาะเมื่อคุณเข้าใจขอบเขตทั้งหมดของข้อกำหนดของ dev ดังกล่าว เป็นที่น่าเกรงขามและใกล้ชิดที่จะติดป้ายกำกับแนวทางของเขาในฐานะ“ ไม่มีเหตุผลที่ดีที่จะทำอย่างนี้” ที่ถูกกล่าวว่าใช่ฉันจะเห็นด้วยกับวิธีการของโจชัวเพื่อให้ง่ายถ้าคุณไม่มีเหตุผลที่จะทำอย่างอื่น
dooleyo

14

สำหรับตัวเลือก # 1 ฉันไม่เชื่อว่ามีการจัดรูปแบบวันที่เกี่ยวข้อง อาจเป็นไปได้ภายใต้ประทุน แต่ฉันคิดว่ามันไม่ได้หัก วันที่จะถูกเก็บไว้ในรูปแบบISO 8601

สำหรับตัวเลือก # 2 ให้ใช้-setDouble:forKey:และ-doubleForKeyแทนที่จะเป็นfloatเวอร์ชันที่ใช้ นั่นอาจเป็นสาเหตุของข้อผิดพลาดที่แม่นยำของคุณ


ว้าวจอห์น ขอบคุณสำหรับคำตอบที่รวดเร็ว คุณจะใช้ส่วนตัวแบบไหน?
John Gallagher

8
ใช้วันที่โดยตรงไม่ใช่ช่วงเวลา ฉันสงสัยว่า API พื้นฐานดังกล่าวจะใช้งานไม่ได้เมื่อแอพจำนวนมากพึ่งพา
John Calsbeek

ยอดเยี่ยม นั่นคือสัญชาตญาณของฉัน แต่ฉันเห็นโค้ดของบุคคลที่สามโดย dev ที่เคารพซึ่งใช้วิธีการลอยดังนั้นฉันคิดว่ามีเหตุผลที่ดีที่เขาจะใช้มัน เห็นได้ชัดว่าไม่ ขอบคุณอีกครั้งสำหรับคำตอบของคุณ!
John Gallagher

1
เป็นไปได้ว่ารหัสที่คุณเห็นคือผู้ที่ไม่จำประเภทที่สามารถจัดเก็บโดยตรงในรายการคุณสมบัติ
John Calsbeek

2
สำหรับเร็กคอร์ด - 32 บิตลอยมีเพียง 24 บิตเพื่อความถูกต้องดังนั้น 1970 ถึงตอนนี้คือ 40 ปีซึ่งคือ 40 * 365 * 86400 วินาทีและ (40 * 365 * 86 400) / (2 ** 24) = 75 วินาที . ความแม่นยำสองเท่าคือช่วงเวลาของ DateTime และความแม่นยำของ RAW นั้นดีกว่าหนึ่งในล้านของวินาที
Tom Andersen

5

ใช้ NSUserDefaults วันที่จะถูกจัดเก็บในเวลา Zulu ดังนั้นจึงไม่มีปัญหาเรื่องโซนเวลาที่ต้องกังวล เก็บไว้ในเขตเวลาของคุณดึงมันออกมาในเขตเวลาอื่นคุณจะสบายดีระบบจัดการการแปลง (ไม่มีตัวจัดรูปแบบวันที่ที่ต้องกังวล)


0

หากคุณบันทึกวันหมดอายุจาก API กราฟ Facebook ฉันจะใช้* ตัวเลือก 2 * *

ตัวเลือกที่สองสามารถแปลงเป็นสตริงได้อย่างง่ายดาย (โดยใช้ stringWithFormat) ที่สำคัญที่สุดใช้งานได้กับกราฟ API

นอกจากนี้คุณไม่ต้องกังวลกับรูปแบบวันที่ของคุณ การไม่จัดการกับ NSDateFormatter นั้นมีค่าความเป็นไปได้ของข้อผิดพลาด 48 วินาที

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.