NSCoding可以用与存取一般的类对象,需要类成为NSCoding的代理,并且实现编码和解码方法。
假设类Person有name和age两个属性,应该这样设置类:
.h文件:
#import <Foundation/Foundation.h> @interface Person : NSObject <NSCoding> // 注意要成为代理 @property (nonatomic, copy) NSString *name; @property (nonatomic, assign) int age; @end
.m文件
#import "Person.h" @implementation Person /** * 将对象归档的时候调用 * * @param aCoder 编码对象 */ -(void)encodeWithCoder:(NSCoder *)aCoder{ //编码成员变量并存入相应的key [aCoder encodeObject:_name forKey:@"name"]; [aCoder encodeInt:_age forKey:@"age"]; } /** * 将对象从文件中读取的时候调用 * * @param aDecoder 解码对象 * * @return 读取到的对象 */ - (id)initWithCoder:(NSCoder *)aDecoder{ if (self = [super init]) { self.name = [aDecoder decodeObjectForKey:@"name"]; self.age = [aDecoder decodeIntForKey:@"age"]; } return self; } @end
Person *p = [[Person alloc] init]; p.name = @"jack"; p.age = 15; NSString *homePath = NSHomeDirectory(); NSString *docPath = [homePath stringByAppendingPathComponent:@"Documents"]; NSString *filePath = [docPath stringByAppendingPathComponent:@"test.data"]; //归档 [NSKeyedArchiver archiveRootObject:p toFile:filePath];
读取Person的方法:
NSString *homePath = NSHomeDirectory(); NSString *docPath = [homePath stringByAppendingPathComponent:@"Documents"]; NSString *filePath = [docPath stringByAppendingPathComponent:@"test.data"]; //读档(反归档) Person *p = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
一个细节:
假如有一个Student类继承子Person要存储,如果直接存储,只能调用父类的编码方法,因此子类的特有数据不能保存,应该再重新实现归档函数,但是直接调用父类的归档函数即可初始化原来的数据,再初始化自己的即可。
Tip:通过super调用父类方法可以省去原来属性的初始化。
假设Student多一个学号属性no:
@interface Student : Person @property (nonatomic, assign) int no; @end
#import "Student.h" @implementation Student -(void)encodeWithCoder:(NSCoder *)aCoder{ [super encodeWithCoder:aCoder]; [aCoder encodeInt:self.no forKey:@"no"]; } - (id)initWithCoder:(NSCoder *)aDecoder{ if (self = [super initWithCoder:aDecoder]) { _no = [aDecoder decodeIntForKey:@"no"]; } return self; } @end