前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >iOS开发——数据持久化之归档

iOS开发——数据持久化之归档

作者头像
Originalee
发布2018-08-30 10:37:16
5940
发布2018-08-30 10:37:16
举报
文章被收录于专栏:编程之旅

在实际的项目开发中,数据持久化是我们必须要考虑的一个事情,如何把我们需要的数据进行持久化处理。

在此之前,一些轻量级的数据类型我一般比较喜欢用NSUserDefaults来存储,因为首先这是一个单例,而且使用简便,数据之间传递自由,所以很适合用来保存简单的数据。

而昨天我在实际工作中,有一个数组NSMutableArray需要存储,但是使用时,报了一个错误 reason: '*** -[NSUserDefaults setObject:forKey:]: attempt to insert non-property list object,这个报错提示我试图加入一个不支持的数据类型。可是明明NSUserDefaults支持的数据类型有:NSNumber(NSInteger、float、double),NSString,NSDate,NSArray,NSDictionary,BOOL,为什么我的NSArray不能加入呢。后来发现我的数组中的对象,是Model类的对象。

既然涉及到了Model类的对象,就要考虑用归档(NSKeyedArchiver)来处理它了。NSKeyedArchiver能够存储的数据范围很广,因为它对应着MVC中的Model层,即实体类。在程序中,我们会在Model层定义很多的entity,例如name、room、device等。

那么对自定义对象的归档显得重要的多,因为很多时候我们都要在程序退出时保存数据,再程序恢复时重新加载,那么,归档便是一个好的选择。

接下来我们来讲讲NSKeyedArchiver的使用。

  • 要使对象可以归档,对象必须实现NSCoding协议,大部分对象都符合NSCoding的协议,一般我们可以在我们的Model类中实现NSCoding协议。

遵循NSCoding协议,我们需要实现两个方法。

  • - (void)encodeWithCoder:(NSCoder *)aCoder;
  • - (nullable instancetype)initWithCoder:(NSCoder *)aDecoder;
  • 同时也建议对象实现NSCoping协议,该协议允许复制对象,遵循该协议要实现- (id)copyWithZone:(nullable NSZone *)zone;方法

下面我们来看归档协议方法的实现

代码语言:javascript
复制
-(void)encodeWithCoder:(NSCoder *)aCoder{
// 这里放置需要持久化的属性
    [aCoder encodeObject:_deviceType forKey:@"deviceType"];
    [aCoder encodeObject:_roomType forKey:@"roomType"];
    [aCoder encodeObject:_brand forKey:@"brand"];
    [aCoder encodeObject:_version forKey:@"version"];
}

接下来是解档的协议方法实现

代码语言:javascript
复制
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder{
//  这里务必和encodeWithCoder方法里面的内容一致,不然会读不到数据
    if (self = [super init]) {
        self.deviceType = [aDecoder decodeObjectForKey:@"deviceType"];
        self.roomType = [aDecoder decodeObjectForKey:@"roomType"];
        self.brand = [aDecoder decodeObjectForKey:@"brand"];
        self.version = [aDecoder decodeObjectForKey:@"version"];
    }
    return self;
}

接下来是遵循了NSCopying协议的方法实现

代码语言:javascript
复制
#pragma mark NSCoping
- (id)copyWithZone:(NSZone *)zone {
    AddDeviceModel *copy = [[[self class] allocWithZone:zone] init];
    copy.deviceType = [self.deviceType copyWithZone:zone];
    copy.roomType = [self.roomType copyWithZone:zone];
    copy.brand = [self.brand copyWithZone:zone];
    copy.version = [self.version copyWithZone:zone];
    return copy;
}
  • 特别注意 如果需要归档的类是某个自定义类的子类时,就需要在归档和解档之前先实现父类的归档和解档方法。即 [super encodeWithCoder:aCoder][super initWithCoder:aDecoder] 方法

使用

因为之前我提过 我们要存储一个数组,那么我们可以把数组中的数据转化成NSData类型来存储,使用+ (NSData *)archivedDataWithRootObject:(id)rootObject;方法。即 :

代码语言:javascript
复制
        NSData *data = [NSKeyedArchiver archivedDataWithRootObject:_dataSource];
        [[NSUserDefaults standardUserDefaults] setObject:data forKey:kEditInfraredRepeater];
        [[NSUserDefaults standardUserDefaults]synchronize];

三行代码,就把NSKeyedArchiver和NSUserDefaults结合来存储数据了。

而要解档使用数据,只要使用解档NSKeyedUnarchiver类中的+ (nullable id)unarchiveObjectWithData:(NSData *)data;方法就可以实现

代码语言:javascript
复制
        NSData *data = [[NSUserDefaults standardUserDefaults] objectForKey:kEditInfraredRepeater];
        NSArray *array = [NSKeyedUnarchiver unarchiveObjectWithData:data];
        _dataSource = [NSMutableArray arrayWithArray:array];

同样也是三行代码实现。

以上就是最简单的归档解档数据持久化的实现方式,至于如何用runtime进行自动归档解档,就又需要日后深入研究了。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2016.05.19 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档