要点:
1、归档即我们常说的序列化,有归档当然就有反归档,反归档即我们常说的反序列化。iOS对NSObject对象进行归档,前提是该对象实现了NSCoding协议;
Foundation中的NSString、NSDictionary、NSArray、NSMutalbeString、NSMutalbeDictionary、NSMutableArray都直接或间接实现了NSCoding协议,所以你可以使用类方法:NSKeyedArchiverarchivedDataWithRootObject:将对象归档为NSData对象,有了NSData对象你就可以存储文件了。那对于项目中更多的NSObject子类,要想被归档,也需要实现NSCoding协议(可以参考下面的MQLPerson类实现)。
2、完成了归档,就说说存储。这里介绍三种方式:
- 将归档的结果NSData对象,使用NSUserDefaults存储(NSUserDefaults操作的是键值对的plist文件)
- 使用类方法NSKeyedArchiverarchiveRootObject:toFile:直接将对象归档到目标文件(缺点是是只能归档一个对象到文件)
- 创建NSKeyedArchiver对象,归档多个对象、基本类型变量到同一个文件(这里能体现出归档的本质其实是在编码,是对字节块编码及拼接)
//MQLPerson头文件begin/
#import <Foundation/Foundation.h>
@interface MQLPerson :NSObject<NSCoding>
@property (nonatomic,copy) NSString *name;
@property (nonatomic,assign) NSUInteger age;
-(NSString*)description;
@end
//MQLPerson头文件end/
//MQLPerson实现文件begin/
#import "MQLPerson.h"
@implementation MQLPerson
-(instancetype)init{
self = [superinit];
if (self) {
_name =@"zhangsan";
_age = 20;
}
returnself;
}
- (void)encodeWithCoder:(NSCoder *)aCoder{
[aCoder encodeObject:_nameforKey:@"name"];
[aCoder encodeInteger:_ageforKey:@"age"];
}
- (nullableinstancetype)initWithCoder:(NSCoder *)aDecoder{
self = [superinit];
if (self) {
_name = [aDecoderdecodeObjectForKey:@"name"];
_age = [aDecoderdecodeIntegerForKey:@"age"];
}
returnself;
}
-(NSString*)description{
return [NSStringstringWithFormat:@"%@, %lu",_name, (unsignedlong)_age];
}
@end
//MQLPerson实现文件end/
在测试类中添加下面的方法:
//1、使用userdefault存储归档的NSData对象
-(void)archieve0:(id)sender{
MQLPerson *person = [MQLPersonnew];
NSData *data = [NSKeyedArchiverarchivedDataWithRootObject:person];
NSUserDefaults *ud = [NSUserDefaultsstandardUserDefaults];
[ud setObject:dataforKey:@"Person"];
[ud synchronize];
}
-(void)unarchieve0:(id)sender{
NSUserDefaults *ud = [NSUserDefaultsstandardUserDefaults];
NSData *data = [udobjectForKey:@"Person"];
if(data){
MQLPerson *person = [NSKeyedUnarchiverunarchiveObjectWithData:data];
NSLog(@"person = %@", person);
}
}
//2、归档一个对象到文件
-(void)archieve1:(id)sender{
NSArray *paths =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSString *docDir = [pathsobjectAtIndex:0];
NSString *filePath = [docDirstringByAppendingPathComponent:@"atany.archiver"];//添加储存的文件名
MQLPerson *person = [MQLPersonnew];
BOOL flag = [NSKeyedArchiverarchiveRootObject:persontoFile:filePath];
if (flag) {
NSLog(@"archieve ok");
}
}
-(void)unarchieve1:(id)sender{
NSArray *paths =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSString *docDir = [pathsobjectAtIndex:0];
NSString *filePath = [docDirstringByAppendingPathComponent:@"atany.archiver"];//添加储存的文件名
MQLPerson *person = [NSKeyedUnarchiverunarchiveObjectWithFile:filePath];
NSLog(@"%@", person);
}
//3、归档多个对象到同一文件
-(void)archieve2:(id)sender{
//准备数据
CGPoint point =CGPointMake(1.0, 2.0);
NSString *info =@"坐标原点";
NSInteger value = 10;
MQLPerson *person = [MQLPersonnew];person.name =@"lisi";person.age = 32;
//准备archieve对象
NSMutableData *data = [[NSMutableDataalloc]init];
NSKeyedArchiver *archvier = [[NSKeyedArchiveralloc]initForWritingWithMutableData:data];
//对多个对象编码
[archvier encodeCGPoint:pointforKey:@"kPoint"];
[archvier encodeObject:infoforKey:@"kInfo"];
[archvier encodeInteger:valueforKey:@"kValue"];
[archvier encodeObject:personforKey:@"person"];
[archvier finishEncoding];
//write to file
NSString *multiHomePath = [NSHomeDirectory()stringByAppendingPathComponent:@"multi.archiver"];
[data writeToFile:multiHomePathatomically:NO];
}
-(void)unarchieve2:(id)sender{
//read data from file
NSString *multiHomePath = [NSHomeDirectory()stringByAppendingPathComponent:@"multi.archiver"];
NSMutableData *data = [[NSMutableDataalloc]initWithContentsOfFile:multiHomePath];
//prepare 解归档对象
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiveralloc]initForReadingWithData:data];
//解码
CGPoint pointR = [unarchiverdecodeCGPointForKey:@"kPoint"];
NSString *infoR = [unarchiverdecodeObjectForKey:@"kInfo"];
NSInteger valueR = [unarchiverdecodeIntegerForKey:@"kValue"];
MQLPerson *peron = [unarchiverdecodeObjectForKey:@"person"];
[unarchiver finishDecoding];
NSLog(@"%f,%f,%@,%ld, %@",pointR.x,pointR.y,infoR,(long)valueR, peron);
}