2012-12-28 25 views
5

Ứng dụng của tôi sử dụng [NSUserDefaults standardUserDefaults] làm cơ sở dữ liệu nhanh và bẩn để lưu trữ trạng thái về người dùng và chính ứng dụng đó. Sự cố với NSUserDefaults là tính linh hoạt của nó cho phép một mớ hỗn độn lớn xuống dòng, ví dụ khi các tệp khác nhau được đặt và đọc các khóa khác nhau trong từ điển theo cách riêng của chúng. Bạn không bắt buộc phải thực thi các quy tắc, bạn có thể vặn tên khóa v.v.Mẫu nào để gói NSUserDefaults?

Tôi đã viết một trình bao bọc đơn giản "quản lý kiểu" cho NSUserDefaults, cả hai đều giữ các giá trị mặc định khi được sử dụng, ẩn tên của các khóa được sử dụng để tìm nạp các giá trị và đóng gói một số logic bổ sung, chẳng hạn như mã hóa thành NSData, khi lưu trữ và truy xuất các đối tượng từ cửa hàng. Tại thời điểm này họ là tài sản được hỗ trợ bởi một accessor đọc/set, nhưng một cái gì đó là cọ xát tôi sai về nó và tôi tự hỏi nếu có lẽ có một cách thanh lịch hơn để đạt được kết quả tương tự. Có khá nhiều bản mẫu và cú pháp kết thúc là hơi khó chịu. Để cung cấp cho bạn một ví dụ:

.h:

@interface UserDefaultsManager: NSObject 

+ (UserDefaultsManager *)sharedInstance; 

@property (nonatomic, assign) NSInteger somethingImTracking; 

@end 

và .m:

NSString * const kSomethingImTracking= @"SomethingImTracking"; 

@implementation UserDefaultsManager 

[...] 

- (NSInteger)somethingImTracking 
{ 
    return [[[NSUserDefaults standardUserDefaults] objectForKey:kSomethingImTracking] intValue]; 
} 

- (void)setSomethingImTracking:(NSInteger)somethingImTracking 
{ 
    [[NSUserDefaults standardUserDefaults] setInteger:somethingImTracking forKey:kSomethingImTracking]; 
} 

và truy cập:

NSInteger foo = [UserDefaultsManager sharedInstance].somethingImTracking; 
+1

Tôi đang làm * chính xác * điều tương tự trong một trong các ứng dụng của tôi để đóng gói một tập hợp các cài đặt tùy chọn mà ứng dụng của tôi hỗ trợ. BTW - bạn nên tạo kSomethingImTracking tĩnh vì nó chỉ được sử dụng trong tệp .m này. – rmaddy

+0

@rmaddy Mẹo hay, cảm ơn! –

+0

Bạn cũng có thể muốn 'setSomethingImTracking' của mình sao cho (a) có thể thận trọng khi thực hiện' synchronize' sau khi đặt giá trị; và (b) có thể làm 'willChangeValueForKey' trước khi thiết lập giá trị và' didChangeValueForKey' sau khi thiết lập nó, trong trường hợp bạn đã từng triển khai KVO trong tương lai. Nhưng tôi đồng ý rằng đây là cách tốt để cô lập các chi tiết của cài đặt 'NSUserDefaults' của bạn. – Rob

Trả lời

4

Cá nhân tôi sử dụng hằng số chuỗi để lưu trữ các tên khóa và chỉ truy cập trực tiếp đối tượng mặc định của người dùng, nhưng tôi không có xu hướng sử dụng các giá trị mặc định ở mức độ lớn hoặc trong nhiều nhóm khác nhau lừa.

Một cải tiến mà tôi thực hiện đối với mã của bạn là thay thế chúng thành phương pháp lớp học. Không có lợi ích cho một singleton (bạn không duy trì bất kỳ trạng thái, đó là tất cả trong các đối tượng mặc định) và điều này có một chút của mã lặp đi lặp lại xấu xí (...sharedInstance) ra khỏi mô hình sử dụng của bạn.

synchronize không cần thiết để bao gồm mỗi lần bạn đặt. Nó chỉ cần thiết khi truy cập các giá trị mặc định từ các luồng khác nhau trong kế tiếp nhanh chóng. Hệ điều hành cũng tự gọi nó theo định kỳ.

+0

Đó là một điểm tốt, tôi chắc chắn không cần thiết "futureproofing" lớp cho tình trạng tiềm năng nội bộ trong tương lai. Ưu điểm duy nhất mà singleton mang lại là chạy "registerDefaults" một cách uể oải bất cứ khi nào nó được sử dụng lần đầu tiên, nó dễ dàng được thay thế bằng một cuộc gọi riêng trong mã ủy nhiệm ứng dụng. –

+0

Một ưu điểm khác để có singleton là để cung cấp bản NSUserDefaults bạn sẽ sử dụng. Bạn có thể có một tài sản tĩnh, nhưng điều đó có vẻ như một mớ hỗn độn. Và thực sự bạn chỉ có thể quan tâm đến việc tiêm phụ thuộc nếu bạn chuẩn bị viết bài kiểm tra hoặc là một người thực hiện OOP. – rob5408

+0

@ rob5408 trong iOS, chỉ có một trường hợp mặc định. – jrturton

Các vấn đề liên quan