ios学习笔记——对象归档
对象归档是一种序列化方式。为了便于数据传输,先将归档对象序列化为一个文件,然后再通过反归档将数据恢复到对象中。
归档技术可以实现数据的持久化,不过在大量数据和频繁读写的情况下,它就不太适合了。
对一个对象进行归档的条件是:改对象的类必须实现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);
输出结果: