NSData
对象转为NSData 这个过程称为序列化,NSData转对象称为反序列化。
任何对象转NSData,都需要遵循一个协议,就是NSCoding。
NSCoding 是把数据存储在iOS和Mac OS上的一种极其简单和方便的方式,把模型对象直接转变成一个文件,然后再把文件重新加载到内存里,并不需要任何文件解析和序列化的逻辑。通过扩展你的数据类来支持encode 和 decode 功能就可以了。
NSCoding 是一个简单的协议 包含:
-initWithCoder:
-encodeWithCoder:
遵循NSCoding 协议的类可以被序列化和反序列化。
NSCoder 是一个抽象类,抽象类不能被实例化
NSKeyedUnarchiver 从二进制流读取对象
NSKeyedArchiver 把对象写到二进制流中去
举例:
@interface Student : NSObject
@property (nonatomic, strong) NSString *studentName;
@property (nonatomic, strong) NSString *score;
@end
@implementation Student
//解码
-(instancetype)initWithCoder:(NSCoder *)aDecoder{
if (self = [super init]) {
self.studentName = [aDecoder decodeObjectForKey:@"studentName"];
self.score = [aDecoder decodeObjectForKey:@"score"];
}
return self;
}
//编码
-(void)encodeWithCoder:(NSCoder *)aCoder{
[aCoder encodeObject:self.studentName forKey:@"studentName"];
[aCoder encodeObject:self.score forKey:@"score"];
}
@end
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:student];
Student *student2 = [NSKeyedUnarchiver unarchiveObjectWithData:data];
这样就建立了任何对象和NSData 之间的桥梁。
利用NSData 进行存储和深拷贝
实现NSCoding 的类,并序列化数据,有两个好处
1.序列化数据可以直接进行存储
2.序列化数据容易进行完全拷贝
将某个对象转NSData ,然后NSData 转回赋值给新建对象。
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:oldContactsArray];
NSMutableArray *newContactsArray = [NSKeyedUnarchiver unarchiveObjectWithData:data];
NSSecureCoding
使用NSCoding来读写用户数据文件的问题在于,把全部的类编码到一个文件里,也就意味着给了这个文件访问你APP里面实例类的权限。
NSSecureCoding 除了在解码时要指定key和要解码的对象的类,如果要求的类和从文件中解码出的对象的类不匹配,NSCoder会抛出异常,代表数据已经被篡改了。
符合NSSecureCoding 协议并重写了-initWithCoder 的类应该使用 -decodeObjectOfClass:forKey:
而不是 -decodeObjectForKey:
举例
-(instancetype)initWithCoder:(NSCoder *)aDecoder{
if (self = [super init]) {
// self.studentName = [aDecoder decodeObjectForKey:@"studentName"];
// self.score = [aDecoder decodeObjectForKey:@"score"];
self.studentName = [ aDecoder decodeObjectOfClass:[NSString class] forKey:@"studentName"];
self.score = [aDecoder decodeObjectOfClass:[NSString class] forKey:@"score"];
}
return self;
}
NSCoding 是基础类库中将对象归档到文件系统上,或者复制到另一个地址空间的方式。
如果用-decodeObjectForKey: 用于把对象解码成实际的对象,就不能保证创建的对象是预期的结果。
扩展:
关于使用runtime 自定实现NSCoding
http://blog.jobbole.com/67655/
http://iosdevelopertips.com/cocoa/nscoding-without-boilerplate.html