持久化方案之 NSKeyedArchiver 归档

谓归档,就是将复杂对象转化为 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);

你可能感兴趣的:(持久化方案之 NSKeyedArchiver 归档)