美文网首页
NSKeyedArchiver简述

NSKeyedArchiver简述

作者: 高灏轩 | 来源:发表于2018-06-29 17:20 被阅读21次

    1.1关于数据的持久化存储的几种方式

        说到NSKeyedArchiver,也就先要了解下iOS开发中关于数据持久化存储的几种方式:1.属性列表 2.对象归档 3.数据库存储(SQLite) 4.Apple提供的CoreData存储工具,关于以上存储方式的使用场景和各自的优缺点,我在此就不再赘述了,今天主要谈一谈关于第二类存储方式-对象归档的使用方法和特点。

    1.2什么是对象归档

    归档是一种很常用的文件储存方法,几乎任何类型的对象都能够被归档储存(实际上是一种文件保存的形式)。

    苹果提供了NSKeyedArchiver和NSKeyedUnarchiver两个类以供我们把对象序列化和反序列化,在存储之前使用NSKeyedArchiver进行序列化操作,并且写入本地文件,在使用之前使用NSKeyedUnarchiver进行反序列化的操作,以供提取使用!

    1.3什么场景下会使用到对象归档

    在实际的开发过程中,我们会使用各种数据存储的方式。

    如果是简单的进行一些系统提供的类型,例如NSArray,NSDictionary,NSString,BOOL,NSInteger,NSfloat等基本数据类型或者对象,我们可以选择系统提供的NSUserDefault这个单例,使用简单方便,但是仅仅只能对以上这些特定的数据格式进行存储,是否有些局限性?而且属性属性列表这种方式又是否安全呢?可能这些这些条件NSUserDefault都无法满足!

    对于一些规律性的,量级比较大的数据,又有规律可循的数据,我们可以选择建表或者使用Apple提供的CoreData进行持久化的存储!

    那么如果数据的量级不是很大,没有必要动用数据库或者是CoreData这种大规模的杀伤性武器的时候,而且又对数据的安全性和持久性有那么些要求的时候,我们最好去选择对象序列化这种中等杀伤性工具了!

    1.4对象归档的使用方法

    使用归档的方法对系统提供的基本类型和基本对象进行归档的操作,在这里不再阐述了,如果明白了对自定义对象的归档和解档,那么系统的基本数据类型和基本对象的归档和解档也就相对很easy了!

    具体的使用方法我就借用目前我正在开发维护的代码进行以下说明:

    目前我们产品的需求是在用户登录之后,就持久化存储用户的登陆相关信息,在后续使用中不需要再次登陆。当用户没有退出登录,卸载程序后,重新从App Store中现在app后,同样保持登陆状态。

    如果仅仅是登陆之后的登陆状态,使用NSUserDefault完全可以实现,只是安全性不是太好而已,但是当用户在登陆状态卸载并且重新安装app后,仍然要保持登陆状态的话,那这个问题就值得思考下了!

    基于以上需求,也就是说我们要把用户的登陆信息存储在一个地方,这个地方要满足的条件是1.持久化存储,用户登录后,再次打开app不需要重新进行登录      2.用户在登录的状态下卸载app,再次重新安装后,仍然保持卸载前的登陆状态,也就是要完美重现卸载前的状态!

    基于以上的条件,我们自然而然地联想到苹果的sandBox机制,关于苹果的sandBox机制,我们不再详述,最关键的一点是:在sandBox中的Document目录下存储的文件,会根据用户的appleID同步到apple的服务端,也就是说如果再次安装app的时候,此app中的沙盒(sandBox)的Document目录下的文件会被再次还原(用户的app购买信息是和用户的appleID绑定的),那么需求就被完美的满足了,具体的代码实现以及注意事项请继续向下阅读:

    @interface IHomeSession : NSObject

    @property (nonatomic, strong) NSString *sessionId;              //会话Id

    @property (nonatomic, strong) NSDate   *lastSessionDate;    //记录上一次请求时间

    @property (nonatomic, strong) NSString *token;                   //ut值

    @property (nonatomic, strong) NSString *alias;                    //设备别名

    @property (nonatomic, strong) NSString *username;            //用户名

    //序列化对象的单例

    + (IHomeSession *)sharedMemory;

    //保存

    - (void)save;

    //获取ssesionId

    - (NSString *)getSessionId;

    //重置

    - (void)reset;

    @end

    以上是.h文件

    具体属性可以根据自己的需求进行添加

    提供获取序列化单例的方法,方便在项目全局进行获取和使用

    提供保存(save),重置(reset),获取sessionId(getSessionId)的api接口以供使用,也可以根据自己的需求添加api

    最重要的一点,是当前类需要遵循NSCoding协议,NSCoding协议中有两个方法,都是requred方法,遵循该协议后,必须实现。

    以下是.m文件中NSCoding协议的具体实现

    #pragma mark - NSCoding

    - (void)encodeWithCoder:(NSCoder *)aCoder

    {

    [aCoder encodeObject:_sessionId forKey:@"_sessionId"];

    [aCoder encodeObject:_lastSessionDate forKey:@"_lastSessionDate"];

    [aCoder encodeObject:_token forKey:@"_token"];

    [aCoder encodeObject:_username forKey:@"_username"];

    [aCoder encodeObject:_alias forKey:@"_alias"];

    }

    通过以上编码的方法,对当前类中的属性进行逐一的键值编码!

    - (id)initWithCoder:(NSCoder *)aDecoder

    {

    if (self = [super init])

    {

    _sessionId = [aDecoder decodeObjectForKey:@"_sessionId"];

    _alias = [aDecoder decodeObjectForKey:@"_alias"];

    _lastSessionDate = [aDecoder decodeObjectForKey:@"_lastSessionDate"];

    _token = [aDecoder decodeObjectForKey:@"_token"];

    _username = [aDecoder decodeObjectForKey:@"_username"];

    }

    return self;

    }

    通过以上解码的方法,对当前类中的属性,根据键进行逐一的逆向编码,并返回一个当前类的实例!

    实现了以上的协议方法后,我们就可对当前的类对象进行归档和解档的操作了:

    首先我们规定一个归档文件在沙盒中的存储路径,写在一个类方法中,方便取用,为了满足app重新安装后仍然可以获取到最后一次登陆信息的需求,我们把文件存储在沙盒中的第一个文件夹(Document)中,这样可以在程序重新安装后自动回复,原理我在需求分析上已经做了阐述!

    + (NSString *)path

    {

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

    NSString *documentDir = [paths objectAtIndex:0];

    NSString *dstPath = [documentDir stringByAppendingPathComponent:@"user.data"];

    return dstPath;

    }

    归档的方法,我们集成在save的接口中:

    - (void)save

    {

    [NSKeyedArchiver archiveRootObject:self toFile:[IHomeSession path]];

    }

    解档的方法我们集成在单例的获取中,一定要先查找对应路径下的文件是否存在,如果存在进行解档操作,不存在的话重新生成一个单例,这样会增强程序的健壮性,防止误取单例,造成程序崩溃!

    + (IHomeSession *)sharedMemory

    {

    static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{

    if ([[NSFileManager defaultManager] fileExistsAtPath:[IHomeSession path]]) {

    instance = [NSKeyedUnarchiver unarchiveObjectWithData:

    [NSData dataWithContentsOfFile:[IHomeSession path]]];

    }

    else

    {

    instance = [[IHomeSession alloc] init];

    }

    });

    return instance;

    }

    重置的接口中,我们需要删除本地文件,同时将单例中的各种属性恢复到初始状态,然后将初始状态下的对象保存归档!

    - (void)reset

    {

    [[NSFileManager defaultManager] removeItemAtPath:[IHomeSession path] error:nil];

    instance = [[IHomeSession alloc] init];

    instance.sessionId = nil;

    instance.lastSessionDate = nil;

    instance.token = @"default";

    instance.username = nil;

    instance.alias = nil;

    [instance save];

    }

    OK了,以上的关键代码实现之后,归档和解档的操作就可以完美实现了,在程序的任何一个地方都可以依托IHomeSeesion这个单例完成操作了,至于后续需要存储的字段,可以根据产品需求依次添加了!

    相关文章

      网友评论

          本文标题:NSKeyedArchiver简述

          本文链接:https://www.haomeiwen.com/subject/rxnayftx.html