NSUserDefault 儲存自定義物件

六叔發表於2016-01-25

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

那麼在實現 NSCodingNSCoping兩個協議時,則

`- (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;
}

小小拙見,有錯請指出。謝謝!

相關文章