天天看點

Objective-C學習之NSCoding協定

       遵守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

方法