一、使用archiveRootObject进行简单的归档
使用NSKeyedArichiver进行归档、NSKeyedUnarchiver进行接档,这种方式会粗体在写入、读出数据之前对数据进行序列化、反序列化操作。
归档:
NSString *homeDictionary = NSHomeDirectory();//获取根目录
NSString *homePath = [homeDictionary stringByAppendingPathComponent:@"atany.archiver"];//添加储存的文件名
BOOL flag = [NSKeyedArchiver archiveRootObject:@”归档” toFile:homePath];//归档一个字符串
这种方式可以对字符串、数字等进行归档,当然也可以对NSArray与NSDictionary进行归档。返回值Flag标志着是否归档成功,YES为成功,NO为失败。
解档:
[NSKeyedUnarchiver unarchiveObjectWithFile:homePath]
使用NSKeyedUnarchiver进行接档(反序列化)。
这种归档的方式存在一个缺点:只能把一个对象归档进一个文件中,那么怎么对多个对象进行归档呢?
二、对自定义对象进行归档:
以实现登录功能为例:
1、新建model类,继承于NSObject类:
- 声明归档存储所需的属性:principal;unitId;realName;loginName;
- 遵循<NSCoding,NSCopying>协议,并实现必要的方法:
-
归档时调用:**- (void)encodeWithCoder:(NSCoder )aCoder;*
》通过一个给定的archiver把消息接收者进行编码。
》当接收到encodeObject消息的时候,类终端encodeWithCoder方法被调用。 -
解档时调用:**- (instancetype)initWithCoder:(NSCoder )aDecoder;*
》从一个给定unarchiver的数据中返回一个初始化对象。 -
<NSCopying>协议方法:**-(id)copyWithZone:(NSZone )zone;* 》返回消息接收者的一个复制的新实例。
.h
#import <Foundation/Foundation.h>
@interface LoginInfoModel : NSObject<NSCoding,NSCopying>
@property (nonatomic , strong) NSString *principal;
@property (nonatomic , strong) NSString *unitId;
@property (nonatomic , strong) NSString *realName;
@property (nonatomic , strong) NSString *loginName;
@end
.m
#import "LoginInfoModel.h"
@implementation LoginInfoModel
//归档时调用
- (void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:self.principal forKey:@"principal"];
[aCoder encodeObject:self.unitId forKey:@"unitId"];
[aCoder encodeObject:self.realName forKey:@"realName"];
[aCoder encodeObject:self.loginName forKey:@"loginName"];
}
//解档时调用
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
if (self = [super init]) {
_principal = [aDecoder decodeObjectForKey:@"principal"];
_unitId = [aDecoder decodeObjectForKey:@"unitId"];
_realName = [aDecoder decodeObjectForKey:@"realName"];
_loginName = [aDecoder decodeObjectForKey:@"loginName"];
}
return self;
}
-(id)copyWithZone:(NSZone *)zone {
LoginInfoModel *copy = [[[self class] allocWithZone:zone] init];
copy.principal = [self.principal copyWithZone:zone];
copy.unitId = [self.unitId copyWithZone:zone];
copy.realName = [self.realName copyWithZone:zone];
copy.loginName = [self.loginName copyWithZone:zone];
return copy;
}
@end
2、归档
- 在需要调取存档的位置进行存档相关操作(如:在登录成功后,拿到登录信息数据,进行存档。)
- code == 200,代表登录成功(与服务端code码对应就ok);
if (status == 200) {
NSDictionary *params = [response valueForKey:@"data"];
//filePath:归档后保存的位置
NSString *filePath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, true).firstObject stringByAppendingPathComponent:@"/loginInfo/info.plist"];
LoginInfoModel *info = [[LoginInfoModel alloc] init];
info.principal = params[@"principal"];
info.unitId = params[@"unitId"];
info.realName = params[@"realName"];
info.loginName = params[@"loginName"];
//归档:此时会调用LoginInfoModel中的【归档】方法
NSMutableData *data = [[NSMutableData alloc] init];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
[archiver encodeObject:info forKey:@"loginInfo"];
[archiver finishEncoding];
//写入文件
BOOL isWrited = [data writeToFile:filePath atomically:true];
if (isWrited) {
//写入成功
} else {
//写入失败
}
} else {
//error
//登录异常
}
3、解档
在需要读取时,进行以下操作:
//在归档文件夹路径下(即之前的filePath),读取文件(解档)
NSMutableData *data = [[NSMutableData alloc] initWithContentsOfFile:LoginInfoPath];
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
LoginInfoArchive *loginInfo = [unarchiver decodeObjectForKey:LoginUnarchiverKey];
[unarchiver finishDecoding];
//读取数据(使用)
NSString *priprincipal = loginInfo.principal;
NSString *unitId = loginInfo.unitId;
NSString *realName = loginInfo.realName;
NSString *loginName = loginInfo.loginName;
NSLog(@"priprincipal=%@",priprincipal);
NSLog(@"unitId=%@",unitId);
NSLog(@"realName=%@",realName);
NSLog(@"loginName=%@",loginName);
》要将一个自定义的类进行归档,那么类里面的每个属性都必须是可以被归档的,如果是不能归档的类型,我们可以把他转化为NSValue进行归档,然后在读出来的时候在转化为相应的类。