遵守NSCoding协议实现数据存储,但先要了解NSCoder,因为协议目的只是规范,真正进行归档和解档作用的是NSCoder。
1.NSCoder描述
The NSCoder abstract class declares the interface used by concrete subclasses to transfer objects and other values between memory and some other format. This capability provides the basis for archiving (where objects and data items are stored on disk) and distribution (where objects and data items are copied between different processes or threads). The concrete subclasses provided by Foundation for these purposes are NSArchiver, NSUnarchiver, NSKeyedArchiver, NSKeyedUnarchiver, and NSPortCoder. Concrete subclasses of NSCoder are referred to in general as coder classes, and instances of these classes as coder objects (or simply coders). A coder object that can only encode values is referred to as an encoder object, and one that can only decode values as a decoder object.
Overview
NSCoder operates on objects, scalars, C arrays, structures, and strings, and on pointers to these types. It does not handle types whose implementation varies across platforms, such as union, void *, function pointers, and long chains of pointers. A coder object stores object type information along with the data, so an object decoded from a stream of bytes is normally of the same class as the object that was originally encoded into the stream. An object can change its class when encoded, however; this is described in Archives and Serializations Programming Guide.
The AV Foundation framework adds methods to the NSCoder class to make it easier to create archives including Core Media time structures, and extract Core Media time structure from archives.
翻译:
NSCoder的具体子类使用NSCoder抽象类的接口在内存和其他格式之间转换对象和其他数据值,NSCoder可以提供基本的归档——把对象和数据存储在磁盘上,和分配——在不同进程和线程之间复制对象和其他数据。在Foundation框架中会提供NSCoder具体的子类,如:NSArchiver、NSUnarchiver、NSKeyedArchiver、NSKeyUnarchiver和NSPortCoder。NSCoder具体的子类统一称作:编码器类,他们的实例化对象则成为编码器对象,一个编码器对象如果只编码就称做:编码对象,一个编码器对象如果只解码就称作解码对象。
概述
NSCoder可以操作对象、标量、C数组、结构体和字符串,还有这些类型的指针。它不能操作的类型是那些跨平台执行的变量,例如:union、void *、函数指针和长链表的指针。
一个编码器对象储存object类型的信息连同object的数据,因此,一个从字节流解码的对象通常跟最初编码的对象是同一个类。然而,一个对象可以在编码的时候改变它的类;这是描述归档文件和序列化的编程指南。
2.NSCoding的声明
要编码的对象,必须实现NSCoding协议。
//*> 该协议声明在NSObject.h中
@protocol NSCoding
//*> 序列化数据、编码成NSCoder对象
- (void)encodeWithCoder:(NSCoder *)aCoder;
//*> 反序列化数据,解码NSCoder对象
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder;
@end
3.举个例子来使用NSCoding
//*> Animal.h
@interface Animal : NSObject<NSCoding>
@property (nonatomic, strong) NSString * name;
@property (nonatomic, assign) unsigned int sex;
@property (nonatomic, assign) unsigned int age;
@property (nonatomic, strong) NSString * location;
@end
//*> Animal.m
#define kA_name @"name"
#define kA_sex @"sex"
#define kA_age @"age"
#define kA_location @"location"
- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
self = [super init];
if (self)
{
self.name = [aDecoder decodeObjectForKey:kA_name];
self.sex = [aDecoder decodeInt32ForKey:kA_sex];
self.age = [aDecoder decodeInt32ForKey:kA_age];
self.location = [aDecoder decodeObjectForKey:kA_location];
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject:_name forKey:kA_name];
[aCoder encodeInt32:_sex forKey:kA_sex];
[aCoder encodeInt32:_age forKey:kA_age];
[aCoder encodeObject:_location forKey:kA_location];
}
当对象需要保存自身时-encoderWithCoder:
方法被调用
当对象需要加载自身时-initWithCoder:
方法被调用
initWithCode:
和其他init
方法一样,在对对象执行操作之前,需要使用超类对它们进行初始化。为此,可以采用两种方式,具体取决于父类,如果父类采用了NSCoding协议,则应该调用[super initWithCoder:decoder];
否则,只需要调用[super init]
即可。NSObject 不采用NSCoding协议,因此我们可以使用简单的init
方法