Objective-C之数据持久化-对象归档

星落辰屿月似钩

两岸茫茫路成霜

预祝中秋快乐!

2(图取自百度图库)

对象归档是一种序列化方式,有的时候我们为了便于数据传输,我们会将归档对象序列化为一个文件,使用的时候再通过反归档将数据恢复到对象中。对象归档可以实现数据持久化,不过在大量数据和频繁读写的情况下,不适用。虽然没有plist快捷,但是可以将自定义对象写入文件,可以归档集合类,所以无论添加多少对象,将对象写入磁盘的方式是相同的,并不会增加工作量。

对象归档:使用NSKeyedArichiver进行归档,使用NSKeyedUnarchiver进行反归档,另外,归档的对象必须是基本数据类型或实现了NSCoding协议的类的某个实例。

在此我们模拟一个场景,点击Home键退出时对数据进行归档,恢复时进行解档。画面如下(画面连接不再赘述,参照以前站点):

1

我们分开讲解代码,单个对象归档、多个对象归档以及自定义对象归档。

首先归档文件路径我单独写了一个函数获取:

-(NSString *)archiverPath{
NSString *documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)lastObject];
NSString *archiverPath = [documentPath stringByAppendingPathComponent:@"archive.archiver"];
return archiverPath;
}

另外在viewDidLoad方法中注册监听(点击Home键时会发送名为UIApplicationWillResignActiveNotification的通知(有点像安卓的广播)):

//applicationWillResignActive:方法自定义
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillResignActive:) name:UIApplicationWillResignActiveNotification object:[UIApplication sharedApplication]];

单个对象归档:

对单个对象进行归档最简单。利用NSKeyedArchiver的archiveRootObject:toFile:类方法归档,NSKeyedUnarchiver 的unarchiveObjectWithFile:类方法反归档;不过,一个文件只能存储一个对象。

- (void)viewDidLoad {
[super viewDidLoad];
NSFileManager *fileManager = [NSFileManager defaultManager];
// 如果文件存在,反归档。
if ([fileManager fileExistsAtPath:[self archiverPath]]){
// NSKeyedUnarchiver的unarchiveObjectWithFile:类方法,解档
NSString *content = [NSKeyedUnarchiver unarchiveObjectWithFile:[self archiverPath]];
self._userName.text = content == nil ? @"" : content;
}
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillResignActive:) name:UIApplicationWillResignActiveNotification object:[UIApplication sharedApplication]];
}

// 点击Home键时归档。
-(void)applicationWillResignActive:(NSNotification *)notify{
// NSKeyedArchiver的archiveRootObject:toFile:类方法,归档。将self._userName.text对象归档到archive.archiver文件,返回值为归档是否成功。
// 这种方式可以对字符串、数字等进行归档,当然也可以对NSArray与NSDictionary进行归档。
BOOL result = [NSKeyedArchiver archiveRootObject:self._userName.text toFile:[self archiverPath]];
if (!result) {
NSLog(@"归档失败!");
}
}

多个对象归档:

多个对象归档还是使用NSKeyedArchiver 和NSKeyedUnarchiver,不过写入和读取的方式变了,这里是利用NSMutableData的writeToFile:atomically:方法。

- (void)viewDidLoad {
[super viewDidLoad];
NSFileManager *fileManager = [NSFileManager defaultManager];
// 如果文件存在,反归档。
if ([fileManager fileExistsAtPath:[self archiverPath]])

// 利用NSData读取归档数据
NSMutableData *unarchiveData = [NSMutableData dataWithContentsOfFile:[self archiverPath]];
// 创建依赖于NSData对象的NSKeyedUnarchiver反归档对象,用于反归档
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:unarchiveData];

// key和归档时一致。
self._userName.text = [unarchiver decodeObjectForKey:@"UserName"];
self._address.text = [unarchiver decodeObjectForKey:@"Address"];
self._mail.text = [unarchiver decodeObjectForKey:@"Mail"];
[self._datePicker setDate:[unarchiver decodeObjectForKey:@"Birthday"]];

// 结束反归档(不要遗漏)
[unarchiver finishDecoding];
}
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillResignActive:) name:UIApplicationWillResignActiveNotification object:[UIApplication sharedApplication]];
}
// 点击Home键时归档。
-(void)applicationWillResignActive:(NSNotification *)notify{
// 创建依赖于NSMutableData对象的NSKeyedArchiver归档对象。
NSMutableData *archiveData = [[NSMutableData alloc] init];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:archiveData];

//对需要归档的基本数据类型进行归档。反归档时所用key和这里设置的key一致。
[archiver encodeObject:self._userName.text forKey:@"UserName"];
[archiver encodeObject:self._address.text forKey:@"Address"];
[archiver encodeObject:self._mail.text forKey:@"Mail"];
[archiver encodeObject:self._datePicker.date forKey:@"Birthday"];

// 结束归档(不要遗漏)
[archiver finishEncoding];

// 将NSData对象写入文件。
[archiveData writeToFile:[self archiverPath] atomically:YES];
}

自定义对象归档:

一般是实体类,自定义对象必须实现NSCoding协议,实现该协议的encodeWithCoder:和initWithCoder:方法,其实和多对象归档类似,只不过将这些对象放到了一个自定义类里去实现

这里我创建了UserInfo类,继承自NSObject,实现NSCoding协议。

@interface UserInfo : NSObject<NSCoding>

@property(nonatomic,strong) NSString* userName;
@property(nonatomic,strong) NSString* address;
@property(nonatomic,strong) NSString* mail;
@property(nonatomic,strong) NSDate* birthday;

@end


@implementation UserInfo
@synthesize userName = _userName;
@synthesize address = _address;
@synthesize mail = _mail;
@synthesize birthday = _birthday;

- (void)encodeWithCoder:(NSCoder *)aCoder{
[aCoder encodeObject:_userName forKey:@"UserName"];
[aCoder encodeObject:_address forKey:@"Address"];
[aCoder encodeObject:_mail forKey:@"Mail"];
[aCoder encodeObject:_birthday forKey:@"Birthday"];
}
- (id)initWithCoder:(NSCoder *)aDecoder{
if (self = [super init]) {
_userName = [aDecoder decodeObjectForKey:@"UserName"];
_address = [aDecoder decodeObjectForKey:@"Address"];
_mail = [aDecoder decodeObjectForKey:@"Mail"];
_birthday = [aDecoder decodeObjectForKey:@"Birthday"];
}
return self;
}
@end

这样在外面,我们只需要归档反归档UserInfo对象就可以了。

- (void)viewDidLoad {
[super viewDidLoad];

NSFileManager *fileManager = [NSFileManager defaultManager];
// 如果文件存在,反归档。
if ([fileManager fileExistsAtPath:[self archiverPath]]){

// 利用NSData读取归档数据
NSMutableData *unarchiveData = [NSMutableData dataWithContentsOfFile:[self archiverPath]];
// 创建依赖于NSData对象的NSKeyedUnarchiver反归档对象,用于反归档
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:unarchiveData];

UserInfo *userInfo = [unarchiver decodeObjectForKey:@"UserInfo"];
self._userName.text = userInfo.userName;
self._address.text = userInfo.address;
self._mail.text = userInfo.mail;
[self._datePicker setDate:userInfo.birthday];

// 结束反归档(不要遗漏)
[unarchiver finishDecoding];
}
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillResignActive:) name:UIApplicationWillResignActiveNotification object:[UIApplication sharedApplication]];
}

- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
// 点击Home键时归档。
-(void)applicationWillResignActive:(NSNotification *)notify{
// 创建依赖于NSMutableData对象的NSKeyedArchiver归档对象。
NSMutableData *archiveData = [[NSMutableData alloc] init];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:archiveData];

UserInfo *userInfo = [[UserInfo alloc] init];
userInfo.userName = self._userName.text;
userInfo.address = self._address.text;
userInfo.mail = self._mail.text;
userInfo.birthday = self._datePicker.date;
[archiver encodeObject:userInfo forKey:@"UserInfo"];

// 结束归档(不要遗漏)
[archiver finishEncoding];

// 将NSData对象写入文件。
[archiveData writeToFile:[self archiverPath] atomically:YES];
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值