在開(kāi)發(fā)過(guò)程中,有時(shí)我們需要將自定義的一個(gè)數(shù)據(jù)模型進(jìn)行存儲(chǔ),這時(shí)候可以選擇歸檔的方式進(jìn)行存儲(chǔ)桃漾,在實(shí)現(xiàn)存儲(chǔ)過(guò)程贷盲,需要遵守NSCoding協(xié)議淘这,并且需要實(shí)現(xiàn)NSCoding的兩個(gè)協(xié)議
- (void)encodeWithCoder:(NSCoder *)aCoder; /**< 歸檔操作 */
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder; /**< 解檔操作 */
按照平常的方式我們需要每添加一個(gè)屬性,在歸檔操作方法和解檔操作方法中巩剖,都需要加入相對(duì)應(yīng)的屬性歸檔和解檔操作
自定義了一個(gè)數(shù)據(jù)模型铝穷,有三個(gè)屬性,進(jìn)行歸檔存儲(chǔ)
@interface MovieModel : NSObject <NSCoding>
@property (nonatomic, copy) NSString *title; /**< 電影名 */
@property (nonatomic, copy) NSMutableString *genres; /**< 電影種類(lèi) */
@property (nonatomic, copy) NSString *imagesUrl; /**< 電影圖片 */
@end
實(shí)現(xiàn)N?SCoding的歸檔協(xié)議方法
/**
* 歸檔操作
*
* @param aCoder
*/
- (void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:_title forKey:@"title"];
[aCoder encodeObject:_imagesUrl forKey:@"imagesUrl"];
[aCoder encodeObject:_genres forKey:@"genres"];
}
再實(shí)現(xiàn)NSCoding的解檔協(xié)議方法
/**
* 解檔操作
*
* @param aDecoder
*
* @return
*/
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder {
if (self = [super init]) {
_title = [aDecoder decodeObjectForKey:@"title"];
_imagesUrl = [aDecoder decodeObjectForKey:@"imagesUrl"];
_genres = [aDecoder decodeObjectForKey:@"genres"];
}
return self;
}
其中佳魔,每個(gè)屬性歸檔解檔操作中的key都是唯一的曙聂,并且同一個(gè)屬性的歸檔和解檔操作對(duì)應(yīng)的key必須要相同,如果數(shù)據(jù)模型的屬性稍微多一點(diǎn)鞠鲜,工作量就有點(diǎn)繁瑣宁脊,所以采取用runtime的反射機(jī)制來(lái)歸檔和解檔操作比平常操作更方便和簡(jiǎn)潔
/**
* 歸檔
*
* @param aCoder
*/
- (void)encodeWithCoder:(NSCoder *)aCoder {
unsigned int count = 0;
// 利用runtime獲取實(shí)例變量的列表
Ivar *ivars = class_copyIvarList([self class], &count);
for (int i = 0; i < count; i ++) {
// 取出i位置對(duì)應(yīng)的實(shí)例變量
Ivar ivar = ivars[i];
// 查看實(shí)例變量的名字
const char *name = ivar_getName(ivar);
// C語(yǔ)言字符串轉(zhuǎn)化為NSString
NSString *nameStr = [NSString stringWithCString:name encoding:NSUTF8StringEncoding];
// 利用KVC取出屬性對(duì)應(yīng)的值
id value = [self valueForKey:nameStr];
// 歸檔
[aCoder encodeObject:value forKey:nameStr];
}
// 記住C語(yǔ)言中copy出來(lái)的要進(jìn)行釋放
free(ivars);
}
/**
* 解檔
*
* @param aDecoder
*
* @return
*/
- (id)initWithCoder:(NSCoder *)aDecoder
{
if (self = [super init]) {
unsigned int count = 0;
Ivar *ivars = class_copyIvarList([self class], &count);
for (int i = 0; i < count; i ++) {
Ivar ivar = ivars[i];
const char *name = ivar_getName(ivar);
NSString *key = [NSString stringWithCString:name encoding:NSUTF8StringEncoding];
id value = [aDecoder decodeObjectForKey:key];
// 設(shè)置到成員變量身上
[self setValue:value forKey:key];
}
free(ivars);
}
return self;
}
這樣子歸檔和解檔操作就完成了,無(wú)論在數(shù)據(jù)模型中添加多少個(gè)屬性贤姆,都不需要再進(jìn)行歸檔和解檔操作榆苞。
基本數(shù)據(jù)類(lèi)型,不能使用NSUInteger