对象归档是一种序列化方式。为了便于数据传输,先将归档对象序列化为一个文件,然后再通过反归档将数据恢复到对象中。
归档技术可以实现数据的持久化,不过在大量数据和频繁读写的情况下,它就不太适合了。
对一个对象进行归档的条件是:改对象的类必须实现NSCoding协议,而且每个成员对象应该是基本数据类型或都是实现NSCoding协议的某个类的实例。
一、使用NSKeyedArchiver进行简单归档
1 NSString * path = NSHomeDirectory();
2 NSString * filePath = [path stringByAppendingPathComponent:@"sjz.txt"];
3 //归档,这里可以是NSString、NSDate、NSArray、NSDictionary等
4 [NSKeyedArchiver archiveRootObject:@"sjz" toFile:filePath];
5
6 //反归档
7 NSString * str = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
这种方式在写入、读出数据之前对数据惊醒序列化、反序列化操作,可以对基本类型数据进行归档。但是这样只能把一个对象归档进一个文件中。
二、多个数据的归档
当有多个数据的时候,我们就需要NSData的帮助了。
NSData封装了字典数据的缓存类,提供了数据文件的方法:
+ (instancetype)dataWithContentsOfFile:(NSString *)path
+ (instancetype)dataWithContentsOfFile:(NSString *)path options:(NSDataReadingOptions)mask error:(NSError * _Nullable *)errorPtr
- (instancetype)initWithContentsOfFile:(NSString *)path
- (instancetype)initWithContentsOfFile:(NSString *)path options:(NSDataReadingOptions)mask error:(NSError * _Nullable *)errorPtr
上面四个方法用于从文件中读取数据创建NSData对象
- (BOOL)writeToFile:(NSString *)path atomically:(BOOL)atomically
- (BOOL)writeToFile:(NSString *)path options:(NSDataWritingOptions)mask error:(NSError * _Nullable *)errorPtr
这两个方法用于将NSData里的数据写的文件中去
1 //文件路径
2 NSString * path = NSHomeDirectory();
3 NSString * filePath = [path stringByAppendingPathComponent:@"sjz.txt"];
4
5 NSString * str = @"小明";
6 NSString * age = @"10";
7 NSArray * arr = [NSArray arrayWithObjects:@"123", @"456", @"789", nil];
8 NSInteger integer = 10;
9
10 //归档
11 NSMutableData * data = [[NSMutableData alloc] init];
12 NSKeyedArchiver * archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
13 [archiver encodeObject:str forKey:@"name"];
14 [archiver encodeObject:age forKey:@"age"];
15 [archiver encodeObject:arr forKey:@"arr"];
16 [archiver encodeInteger:integer forKey:@"integer"];
17 [archiver finishEncoding];
18 [data writeToFile:filePath atomically:YES];
19
20 //反归档
21 NSMutableData * unData = [[NSMutableData alloc] initWithContentsOfFile:filePath];
22 NSKeyedUnarchiver * unArchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:unData];
23 NSString * name = [unArchiver decodeObjectForKey:@"name"];
24 NSString * ageStr = [unArchiver decodeObjectForKey:@"age"];
25 NSArray * array = [unArchiver decodeObjectForKey:@"arr"];
26 NSInteger intt = [unArchiver decodeIntegerForKey:@"integer"];
27 [unArchiver finishDecoding];
28
29 NSLog(@"name = %@, age = %@", name, ageStr);
30 NSLog(@"%@", array);
31 NSLog(@"%ld", intt);
归档时,我们先将所需的数据归档到NSData中,再将NSData数据写到文件中。
反归档时,我们先从文件中读取数据到NSData中,再根据键值烦归档
第三、自定义对象的归档
上边说的是基本对象的归档,但是我们自己定义的实例对象怎么归档呢?
但我们按Home键将程序后台运行时,很多情况下我们要将数据保存,当程序恢复时,数据重新加载,那么归档是一个好的选择。
我们自定义的类想要实现归档与反归档,必须实现NSCoding协议,并实现协议中的两个方法:- (void)encodeWithCoder:(NSCoder *)aCoder 和 - (instancetype)initWithCoder:(NSCoder *)aDecoder
自定义类:
1 #import <Foundation/Foundation.h>
2
3 @interface JZModel : NSObject <NSCoding>
4
5 @property (nonatomic, strong) NSString * name;
6 @property (nonatomic, assign) NSInteger age;
7 @property (nonatomic, strong) NSString * address;
8
9 @end
1 #import "JZModel.h"
2
3 @implementation JZModel
4
5 //必须实现,归档
6 - (void)encodeWithCoder:(NSCoder *)aCoder
7 {
8 [aCoder encodeObject:_name forKey:@"name"];
9 [aCoder encodeInteger:_age forKey:@"age"];
10 [aCoder encodeObject:_address forKey:@"address"];
11 }
12
13 //必须实现,反归档
14 - (instancetype)initWithCoder:(NSCoder *)aDecoder
15 {
16 self = [super init];
17 if(self){
18 _name = [aDecoder decodeObjectForKey:@"name"];
19 _age = [aDecoder decodeIntegerForKey:@"age"];
20 _address = [aDecoder decodeObjectForKey:@"address"];
21 }
22
23 return self;
24 }
25
26
27 - (NSString *)description
28 {
29 return [NSString stringWithFormat:@"姓名:%@,年龄:%ld,地址:%@", self.name, self.age, self.address];
30 }
31
32 @end
实现归档与反归档的代码:
1 NSString * homePath = NSHomeDirectory();
2 NSString * filePath = [homePath stringByAppendingPathComponent:@"sjz.plist"];
3
4 JZModel * model = [[JZModel alloc] init];
5 model.name = @"jz";
6 model.age = 20;
7 model.address = @"河北大街";
8
9 //归档
10 NSMutableData * data = [[NSMutableData alloc] init];
11 NSKeyedArchiver * archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
12 [archiver encodeObject:model forKey:@"model"];
13 [archiver finishEncoding];
14 [data writeToFile:filePath atomically:YES];
15
16
17 //反归档
18 NSMutableData * data1 = [[NSMutableData alloc] initWithContentsOfFile:filePath];
19 NSKeyedUnarchiver * unArchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data1];
20 JZModel * model1 = [unArchiver decodeObjectForKey:@"model"];
21 [unArchiver finishDecoding];
22
23 NSLog(@"%@", model1);
输出结果: