NSUserDefault 儲存自定義物件
NSUserDefault 只可以儲存 int、bool 等基本資料型別,或者 NSString 、NSArray等 複合型別。但是,如果一個自定義的物件的話,那該怎樣使用呢?
在 所寫的類 中,需要實現兩個協議:NSCoping、NSCoding。
這兩個協議主要實現的方法是:
-
NSCoding
`- (instancetype)initWithCoder:(NSCoder *)aDecoder `- (void)encodeWithCoder:(NSCoder *)aCoder`
-
NSCoping
`- (id)copyWithZone:(NSZone *)zone
eg:
@interface Chinese ()<NSCoding, NSCopying>
@end
@implementation Chinese
`- (instancetype)initWithProvince:(NSString *)province height:(NSInteger)height isMale:(BOOL)isMale {
self = [super init];
if (self) {
_province = province;
_height = height;
_isMale = isMale;
}
return self;
}
`- (void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:self.province forKey:@"province"];
[aCoder encodeInteger:self.height forKey:@"height"];
[aCoder encodeBool:self.isMale forKey:@"isMale"];
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
self = [super init];
if (self) {
self.province = [aDecoder decodeObjectForKey:@"province"];
self.height = [aDecoder decodeIntegerForKey:@"height"];
self.isMale = [aDecoder decodeBoolForKey:@"isMale"];
}
return self;
}
`- (id)copyWithZone:(NSZone *)zone {
Chinese *copyChinese = [[self class] allocWithZone:zone];
copyChinese.province = [self.province copyWithZone:zone];
copyChinese.isMale = self.isMale;
copyChinese.height = self.height;
return copyChinese;
}
類似這樣的形式,自定義的一個類。
在使用上呢,則需要先對 該物件 進行 歸檔,即 archive。
eg:
Chinese *cantonese = [[Chinese alloc] initWithProvince:@"廣東" height:180 isMale:YES];
NSData *chineseDate = [NSKeyedArchiver archivedDataWithRootObject:cantonese];
[[NSUserDefaults standardUserDefaults] setObject:chineseDate forKey:@"chinese"];
這是由於 本地化儲存 的特性導致的。所以需要先歸檔成 NSData
型別,在對其進行儲存。因此,在取出資料的時候,得到的是 NSData
資料型別,再對其進行解檔 得到相對應的物件。eg:
NSData *chineseData = [[NSUserDefaults standardUserDefaults] objectForKey:@"chinese"];
Chinese *chinese = [NSKeyedUnarchiver unarchiveObjectWithData:chineseData];
基本流程,差不多就是這樣。
那如果 自定義物件 的 一個屬性 也是 自定義物件的話,比如:
@interface Person : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) Chinese *chinese;
@end
那麼在實現 NSCoding
和 NSCoping
兩個協議時,則
`- (instancetype)initWithCoder:(NSCoder *)aDecoder {
self = [super init];
if (self) {
self.name = [aDecoder decodeObjectForKey:@"name"];
self.chinese = [aDecoder decodeObjectOfClass:[Chinese class] forKey:@"chinese"];
}
return self;
}
`- (void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:self.name forKey:@"name"];
[aCoder encodeObject:self.chinese forKey:@"chinese"];
}
`- (id)copyWithZone:(NSZone *)zone {
Person *copyPerson = [[self class] allocWithZone:zone];
copyPerson.name = [self.name copyWithZone:zone];
copyPerson.chinese = [self.chinese copyWithZone:zone];
return copyPerson;
}
小小拙見,有錯請指出。謝謝!