使用NSKeyedArchiver持久化数据

NSKeyedArchiver 是 iOS 中数据持久化方式中的一种。凡是遵守 NSCoding 协议的对象都可以使用 NSKeyedArchiver 进行数据持久化。 

像一些系统的 NSString, NSArray,NSDictionary等都已经遵守了 NSCoding协议,所以可以可以使用NSKeyedArchiver 进行持久化。

BOOL ret = [NSKeyedArchiver archiveRootObject:arr toFile:path];

直接将对象arr 存储到指定的目录下。

或者是

NSData *data = [NSKeyedArchiver archivedDataWithRootObject:arr];
[data writeToFile:path atomically:YES];

将对象转化成二进制后然后再写到相应的目录下。

对于我们自定义的对象如果要使用 NSKeydArchiver 来持久化,则需要改对象遵守 NSCoding 协议并实现相应的代理方法。

.h
@interface User : NSObject<NSCoding>

@property(nonatomic, copy) NSString *name;
@property(nonatomic, copy) NSString *addr;
@property(nonatomic, copy) NSString *tel;
@property(nonatomic, assign) CGFloat weight;
@property(nonatomic, assign) CGFloat height;

@end

.m
// 实现相应的代理方式
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
    if (self = [super init]) {
        self.name = [aDecoder decodeObjectForKey:@"name"];
        self.addr = [aDecoder decodeObjectForKey:@"addr"];
        self.tel = [aDecoder decodeObjectForKey:@"tel"];
        self.height = [[aDecoder decodeObjectForKey:@"height"] floatValue];
        self.weight = [[aDecoder decodeObjectForKey:@"weight"] floatValue];    
    }
    return self;
}

- (void)encodeWithCoder:(NSCoder *)aCoder {
    [aCoder encodeObject:self.name forKey:@"name"];
    [aCoder encodeObject:self.addr forKey:@"addr"];
    [aCoder encodeObject:self.tel forKey:@"tel"];
    [aCoder encodeObject:@(self.height) forKey:@"height"];
    [aCoder encodeObject:@(self.weight) forKey:@"weight"];
@end

以上的写法对于属性值少的对象来说还好,但是如果对象有十几二十个属性那可就要麻烦死了。利用runtime和kvc可以解决这一问题。

- (instancetype)initWithCoder:(NSCoder *)aDecoder {
    if (self = [super init]) { 
        unsigned int outCount;
        Ivar *varList = class_copyIvarList([self class], &outCount);
        for (int i = 0; i<outCount; i++) {
            Ivar var = varList[i];
            const char *varName = ivar_getName(var);
            NSString *key = [[NSString alloc] initWithUTF8String:varName];
            id value = [aDecoder decodeObjectForKey:key];
            /** kvc set value */
            [self setValue:value forKey:key];
        }
    }
    return self;
}

- (void)encodeWithCoder:(NSCoder *)aCoder {  
    unsigned int outCount;
    Ivar *varList = class_copyIvarList([self class], &outCount);
    
    for (int i = 0; i<outCount; i++) {
        Ivar var = varList[i];
        const char *varName = ivar_getName(var);
        NSString *key = [[NSString alloc] initWithUTF8String:varName];
        /** kvc get object */
        id value = [self valueForKey:key];
        [aCoder encodeObject:value forKey:key];
    }
}

以上是使用 NSKeyedArchiver 进行归档 。

使用NSkeyedArchiver进行解档就相对简单了。

NSArray *userArr = [NSKeyedUnarchiver unarchiveObjectWithFile:[kDocPath stringByAppendingPathComponent:@"user.archiver"]];

NSKeyedArchiver 相比于 NSUserDefaults 和 Plist文件持久化方案最大的优势在于:可以存储自定义对象。

有一点需要注意:解档出来的对象都是不可变的,即使你存储的对象是可变的容器或者字符串。

(如:你存储的对象是 NSMutableArray,存进去再取出来的时候就自动转成了NSArray了。)

但是 NSKeyedArchiver 也有不足之处:相对于类似sqlite或者codedata等存储数据的量级还是小了点,so 使用 NSKeyedArchiver 不宜于存储大量的数据。

 

 

转载于:https://my.oschina.net/zhxx/blog/866518

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值