谓归档,就是将复杂对象转化为 NSData 类型数据 (复杂-->归档-->NSData--->WriteToFile)。
反归档就是将 NSData 类型数据转化为复杂对象 (读取文件-->NSData-->反归档--->复杂对象)。
如果对象是 NSString、NSDictionary、NSArray、NSData、NSNumber 等类型,可以直接用 NSKeyedArchiver 进行归档和恢复。不是所有的对象都可以直接用这种方法进行归档,只有遵守了 NSCoding 协议的对象才可以。下面进行具体分析。
1.对 Foundation 框架的对象进行归档
如果对象是 NSString、NSDictionary、NSArray、NSData、NSNumber 等类型,可以直接用 NSKeyedArchiver 进行归档和恢复。
/获取路径
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *document = paths[0];
NSString *filePath = [document stringByAppendingString:@"file.plist"];
//归档
NSArray *array = [NSArray arrayWithObjects:@"1",@"2",@"3", nil];
[NSKeyedArchiver archiveRootObject:array toFile:filePath];
//解档
NSArray *arrayCopy = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
NSLog(@"arrayCopy - %@",arrayCopy);
2.对自定义的对象进行归档
对于自定义的对象,我们需要实现 NSCoding 协议才可以进行归档。
NSCoding 协议有 2 个方法 :
encodeWithCoder:
每次归档对象时,都会调用这个方法。一般在这个方法里面指定如何归档对象中的每个实例变量,可以使用 encodeObject:forKey: 方法归档实例变量。
initWithCoder:
每次从文件中恢复(解码)对象时,都会调用这个方法。一般在这个方法里面指定如何解码文件中的数据为对象的实例变量,可以使用 decodeObject:forKey 方法解码实例变量
下面给出具体例子 :
Student *student = [[Student alloc] init];
student.name = @"Tom";
student.sex = @"male";
//归档
[NSKeyedArchiver archiveRootObject:student toFile:filePath];
//解档
Student *studentCopy = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
NSLog(@"name - %@,sex - %@",studentCopy.name,studentCopy.sex);
Student.h
#import @interface Student : NSObject@property (nonatomic, strong) NSString *name;@property (nonatomic, strong) NSString *sex;@end复制代码
Student.m
#import "Student.h"@implementation Student#pragma mark - NSCoding//归档- (void)encodeWithCoder:(NSCoder *)aCoder { [aCoder encodeObject:self.name forKey:@"name"]; [aCoder encodeObject:self.sex forKey:@"sex"];}//解档- (instancetype)initWithCoder:(NSCoder *)aDecoder { if (self = [super init]) { self.name = [aDecoder decodeObjectForKey:@"name"]; self.sex = [aDecoder decodeObjectForKey:@"sex"]; } return self;}@end复制代码
注意:
如果父类也遵守了 NSCoding 协议,请注意,应该在 encodeWithCoder: 方法中加上一句
[super encodeWithCode:aCoder];复制代码
确保继承的实例变量也能被编码,即也能被归档。应该在 initWithCoder: 方法中加上一句
self = [super initWithCoder:aDecoder];复制代码
确保继承的实例变量也能被解码,即也能被恢复。
3.对多个对象进行归档(单个对象也适用)
这些对象当然也要遵守 NSCoding 协议,并且 NSString、NSDictionary、NSArray、NSData、NSNumber 等类型默认遵守 NSCoding 协议。
3.1 先序列化再将 data 存入磁盘
//多个对象Student *student1 = [[Student alloc] init];student1.name = @"Tom";student1.sex = @"male";Student *student2 = [[Student alloc] init];student2.name = @"Lina";student2.sex = @"female";NSArray *array = [NSArray arrayWithObjects:student1,student2, nil];//归档NSData *data = [NSKeyedArchiver archivedDataWithRootObject:array];//序列化[NSKeyedArchiver archiveRootObject:data toFile:filePath];//存入磁盘//解档NSData *dataCopy = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];NSArray *arrayCopy = [NSKeyedUnarchiver unarchiveObjectWithData:dataCopy];NSLog(@"name - %@,sex - %@",arrayCopy[1].name,arrayCopy[1].sex);
3.2 先关联 data,序列化后再存入磁盘
//多个对象
Student *student1 = [[Student alloc] init];
student1.name = @"Tom";
student1.sex = @"male";
Student *student2 = [[Student alloc] init];
student2.name = @"Lina";
student2.sex = @"female";
//归档
NSMutableData *data = [NSMutableData data];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];//关联data
[archiver encodeObject:student1 forKey:@"student1"];//序列化
[archiver encodeObject:student2 forKey:@"student2"];
[archiver finishEncoding];//千万不要忘记!!!
//写入磁盘
[data writeToFile:filePath atomically:YES];
//解档
NSData *dataCopy = [NSData dataWithContentsOfFile:filePath];
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:dataCopy];
Student *student1Copy = [unarchiver decodeObjectForKey:@"student1"];
Student *student2Copy = [unarchiver decodeObjectForKey:@"student2"];
NSLog(@"name - %@,sex - %@",student1Copy.name,student1Copy.sex);
NSLog(@"name - %@,sex - %@",student2Copy.name,student2Copy.sex);