1. NSCoding协议。如果一个类要具有归档/解归档功能,需要实现NSCoding协议
ProtocolNSCoding
The NSCoding
protocol declares the two methods that a class must implement so that instances of that class can be encoded and decoded. This capability provides
the basis for archiving (where objects and other structures are stored on disk) and distribution (where objects are copied to different address spaces).
2. 归档和解归档。对于实现了NSCoding协议的类,我们可以用对其进行归档/解归档操作,将对象保存到文件中以及从文件中还原回来,举例NSArray对象的归档
//归档,将对象保存到文件
NSArray* array1 = [NSArray arrayWithObjects:@"zhangsan",@"lisi", nil];
//确定好路径,文件名随意取的,不一定就是arc
NSString* filePath = [NSHomeDirectory() stringByAppendingPathComponent:@"array.arc"];
BOOL bRet = [NSKeyedArchiver archiveRootObject:array1 toFile:filePath];
if( bRet == YES) {
NSLog(@"归档成功");
}
//解归档,将文件还原为对象
NSArray* array2 = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
for(NSString* s in array2) {
NSLog(@"%@", s);//此处能顺利的将array1中的元素打印出来,说明解归档成功
}
当然还有另一种方式,不局限于一种数据类型保存为一个文件,比较灵活一点
NSArray* array = [NSArray arrayWithObjects:@"zhangsan", @"wangwu",nil];
//此NSMutaleData用于存储归档对象中的数据
NSMutableData* data = [NSMutableData data];
//创建归档对象
NSKeyedArchiver* archier = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
//由archier负责编码,将要保存的数据存储到data对象中
[archier encodeObject:array forKey:@"array"];
[archier encodeInt:100 forKey:@"scope" ];
[archier encodeObject:@"jack" forKey:@"name"];
//完成编码,将归档数据填充至data中,此时data中已经存储了归档对象的数据
[archier finishEncoding];
[archier release];
NSString* filePath = [NSHomeDirectory() stringByAppendingPathComponent:@"ar.text"];
BOOL bRet = [data writeToFile:filePath atomically:YES];
if( bRet == YES) {
NSLog(@"归档成功");
}
//解归档
NSString* filePath = [NSHomeDirectory() stringByAppendingPathComponent:@"ar.text"];
//读取归档数据
NSData* data = [[NSData alloc] initWithContentsOfFile:filePath];
//创建解归档对象,对data中的数据进行解归档
NSKeyedUnarchiver* unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
//还原数据
NSArray* array2 = [unarchiver decodeObjectForKey:@"array"];
int scope2 = [unarchiver decodeObjectForKey:@"scope"];
NSString* name2 = [unarchiver decodeObjectForKey:@"name"];
//此处能顺利打印出来原来的数据,说明解归档正常
NSLog(@"array = %@",array2);
NSLog(@"scope = %d",scope2);
NSLog(@"name = %@",name2);
3. 自定义类实现编码协议NSCoding。假设我们自己创建一个类Person如下
@interface Person : NSObject
@property (nonatomic, copy) NSString* name;
@property (nonatomic, assign) NSInteger age;
@property (nonatomic, retain) NSArray* apples;
@end
这样是不能直接使用上述的两种方式进行归档和解归档的,需要实现NSCoding协议,修改如下
//.h文件
//类只有实现NSCoding协议才能具有归档功能
@interface Person : NSObject <NSCoding>
@property (nonatomic, copy) NSString* name;
@property (nonatomic, assign) NSInteger age;
@property (nonatomic, retain) NSArray* apples;
@end
.m文件中实现协议的两个方法
#import "Person.h"
@implementation Person
//归档时被调用
- (void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:_name forKey:@"name"];
[aCoder encodeInteger:_age forKey:@"age"];
[aCoder encodeObject:_apples forKey:@"apples"];
}
//解归档时这个方法被调用,将文件数据解编码到当前对象中
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder {
self = [super init];
if(self != nil) {
// _name = [aDecoder decodeObjectForKey:@"name"];//这样指针指过去,除非retain,否则如果该字符串对象销毁了就会出错,所以需要用copy
_name = [[aDecoder decodeObjectForKey:@"name"] copy];//应该使用copy
_age = [aDecoder decodeIntegerForKey:@"age"];
// _apples = [aDecoder decodeObjectForKey:@"apples"];//同上,这样写不对
_apples = [[aDecoder decodeObjectForKey:@"apples"] copy];
}
return self;
}
@end
//自定义归档对象
Person* person = [[Person alloc] init];
person.name = @"zhangsan";
person.age = 23;
person.apples = @[@"iphone",@"mac",@"ipad"];
NSString* filePerson = [NSHomeDirectory() stringByAppendingPathComponent:@"person.arc"];
BOOL b = [NSKeyedArchiver archiveRootObject:person toFile:filePerson];
Person* person2 = [NSKeyedUnarchiver unarchiveObjectWithFile:filePerson];
NSLog(@"name = %@, age = %ld, apples = %@",person2.name, person2.age, person2.apples);