Cách tối ưu để lưu trữ NSDate trong NSUserDefaults là gì?


174

Có hai cách lưu trữ NSDate trong NSUserDefaults mà tôi đã gặp.

Tùy chọn 1 - setObject: forKey:

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

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

Tùy chọn 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];

Ưu và nhược điểm

lựa chọn 1

Điều này có vẻ là nhỏ gọn và hợp lý. Tuy nhiên, tôi đã lo lắng về việc này sẽ xảy ra do lỗi Date Formatter .

Lựa chọn 2

Điều này có vẻ là vụng về. Tôi cũng không chắc về độ chính xác của nó - trong một thử nghiệm tôi đã thực hiện, khi tôi lấy lại ngày trở lại sau 48 giây, mặc dù Apple Docs nói rằng NSTimeInterval có "độ chính xác thứ hai".

Yêu cầu

Dù tôi chọn phương pháp nào thì cũng phải:

  1. Chính xác trong vòng một giây.

  2. Dễ đọc và đáng tin cậy

Câu hỏi của tôi

Là sự không chính xác với Tùy chọn 2 vì tôi đang làm gì đó sai?

Mà trong số hai tùy chọn bạn sẽ sử dụng?

Có lựa chọn nào khác mà tôi không biết?

Cảm ơn!

Câu trả lời:


380

Bạn không cần phải phức tạp hóa mọi thứ. Tại sao bạn chuyển đổi ngày thành một khoảng thời gian (sau đó là khoảng thời gian sang một nguyên thủy khác)? Chỉ[sharedDefaults setObject:theDate forKey:@"theDateKey"] và được thực hiện với nó. NSDate là một trong những "loại chính" được hỗ trợ bởi định dạng PLIST (ngày, số, chuỗi, dữ liệu, từ điển và mảng), vì vậy bạn chỉ có thể lưu trữ trực tiếp.

Xem tài liệu để chứng minh.

Chỉ cần lưu trữ và truy xuất ngày trực tiếp và xem nó Thực hiện đúng (bao gồm cả múi giờ, độ chính xác, v.v.). Không có định dạng liên quan, như những người khác đã nói.


8
Joshua, cảm ơn câu trả lời của bạn. Lý do tôi đã thử cách tiếp cận float hỗn độn ngớ ngẩn chỉ đơn giản là vì tôi đã thấy một nhà phát triển tuyệt vời khác làm điều đó và tôi nghĩ rằng anh ta đã làm nó vì một lý do tốt. Rõ ràng là không. Tôi nên tự tin hơn vào bản năng của mình, đó là sử dụng setObject: forKey: và đã thực hiện với nó.
John Gallagher

7
Tôi hoàn toàn bạo lực đối với những suy nghĩ phức tạp không cần thiết - một đặc điểm tốt cho các nhà phát triển và những người lười biếng nói chung. :-)
Joshua Nozzi

Các trường hợp sử dụng cách tiếp cận như vậy chủ yếu là khi NSUserDefaults được sử dụng làm triển khai lưu trữ tùy chọn người dùng cho phần mềm trung gian chung ...
Coyote

@Coyote: Trong trường hợp đó, nó vẫn được truy cập thông qua NSUserDefaults hoặc được phân tích cú pháp từ tệp danh sách thuộc tính, do đó, việc truy cập hoặc phân tích cú pháp tương tự sẽ mang lại một đối tượng NSDate thích hợp, có thể được chuyển đổi khi cần.
Joshua Nozzi

3
@JohnGallagher [sidebar] Đừng nhầm lẫn việc thực hiện cụ thể của ai đó với người nghèo. Tình cảm ban đầu của bạn "nghĩ rằng anh ấy đã làm điều đó vì một lý do chính đáng ... Rõ ràng là không" chỉ có thể hợp lệ nếu bạn hiểu toàn bộ phạm vi yêu cầu của nhà phát triển nói. Thật là tự phụ và gần gũi khi mù quáng dán nhãn cho cách tiếp cận của mình là "rõ ràng không có lý do chính đáng để làm theo cách này". Điều đó đang được nói, vâng tôi sẽ đồng ý với cách tiếp cận của Joshua để giữ cho nó đơn giản nếu bạn không có lý do gì để làm khác.
dooleyo

14

Đối với tùy chọn # 1, tôi không tin rằng một công cụ định dạng ngày có liên quan. Có thể dưới mui xe, nhưng tôi tưởng tượng nó không bị hỏng. Ngày được lưu trữ ở dạng ISO 8601 .

Đối với tùy chọn # 2, sử dụng -setDouble:forKey:-doubleForKeythay vì các floatphiên bản dựa trên. Đó có thể là nguyên nhân gây ra lỗi chính xác của bạn.


Ồ, John. Cảm ơn câu trả lời rất nhanh của bạn. Mà cá nhân bạn sẽ sử dụng?
John Gallagher

8
Sử dụng ngày trực tiếp, không phải khoảng thời gian. Tôi nghi ngờ rằng một API cơ bản như vậy đã bị hỏng khi rất nhiều ứng dụng dựa vào nó.
John Calsbeek

Thông minh. Đó là bản năng của tôi, nhưng tôi đã thấy mã của bên thứ ba bởi một nhà phát triển đáng kính đã sử dụng phương thức float nên tôi nghĩ sẽ có một số lý do chính đáng để anh ta sử dụng nó. Rõ ràng là không. Cảm ơn một lần nữa cho câu trả lời của bạn!
John Gallagher

1
Có thể mã mà bạn đã thấy là nhà phát triển không nhớ loại nào có thể được lưu trữ trực tiếp trong danh sách tài sản.
John Calsbeek

2
Đối với bản ghi - số float 32 bit chỉ có độ chính xác 24 bit, do đó, 1970 đến nay là 40 năm, tức là 40 * 365 * 86400 giây và (40 * 365 * 86 400) / (2 ** 24) = lỗi 75 giây . Độ chính xác kép là khoảng thời gian DateTime và độ chính xác RAW của nó hiện tốt hơn một phần triệu giây.
Tom Andersen

5

Sử dụng NSUserDefaults; ngày được lưu trữ trong thời gian Zulu, vì vậy không có vấn đề về múi giờ để lo lắng. Lưu trữ nó trong múi giờ của bạn, kéo nó ra trong múi giờ khác, bạn sẽ ổn thôi, hệ thống xử lý chuyển đổi (không phải lo lắng về định dạng ngày).


0

Nếu bạn đang lưu ngày hết hạn từ API đồ thị của Facebook, tôi sẽ sử dụng * Tùy chọn 2 * .

Tùy chọn hai có thể dễ dàng chuyển đổi thành một chuỗi (sử dụng chuỗiWithFormat). Quan trọng nhất, nó hoạt động cho API đồ thị.

Ngoài ra, bạn không phải lo lắng về định dạng ngày của bạn. Không xử lý với NSDateFormatter có khả năng xảy ra lỗi 48 giây.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.