LoginSignup
39
37

More than 5 years have passed since last update.

[Objective-C] NSCodingについてメモ

Last updated at Posted at 2014-07-30

NSCoding、今さらながら色々問題に当たったので情報整理のためにメモ。

例によって、今回のサンプルをGitHubに上げました。

シリアライズ(アーカイブ)するならNSCodingプロトコルの実装は必須

自作のクラスをシリアライズ(アーカイブ)してファイルに保存するには、NSCodingプロトコルで定義されている、以下のふたつのメソッドを実装する必要があります。

@protocol NSCoding

- (void)encodeWithCoder:(NSCoder *)aCoder;
- (id)initWithCoder:(NSCoder *)aDecoder;

@end

encodeWithCoder:aCoderメソッドは、シリアライズするタイミングで呼ばれます。
initWithCoder:aDecoderメソッドは逆に、デシリアライズするタイミングで呼ばれます。対の関係です。

これらのメソッドの実装は必須です。
実装されていない場合、不正な呼び出しでアプリがクラッシュします。

実装する

encode

実装自体はシンプルです。
シリアライズされる際に、シリアライズに必要な要素を、引数で渡されたNSCoderオブジェクトのencode****:forKey:を呼び出します。

encode****の部分には、encodeしたい要素に適切な型を指定します。(e.g. encodeObject, encodeInteger

forKeyによってキーを指定してシリアライズ/デシリアライズすることができます。

サンプルコード

- (void)encodeWithCoder:(NSCoder *)aCoder
{
    [aCoder encodeObject:self.name forKey:@"name"];
    [aCoder encodeInteger:self.age forKey:@"age"];
}

decode

デシリアライズは逆の処理になります。
取り出す際は、自作クラスのプロパティに、decodeされた情報を保持することで復元が完了します。

サンプルコード

- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
    self = [super init];
    if (self) {
        self.name = [aDecoder decodeObjectForKey:@"name"];
        self.age  = [aDecoder decodeIntegerForKey:@"age"];
    }
    return self;
}

これらの情報は、必要なだけシリアライズ/デシリアライズする必要があります。
(逆に必要ないものを省略すると復元されなくなります)

データを保存する

データをシリアライズしたら、あとはそれをファイルに保存します。
最終的なサンプルコードは以下の通りです。
(サンプルは保存してすぐ読み込むだけの意味のないサンプルです)


#import "NCTViewController.h"

#import "NCTSample.h"

static NSString *kFileName = @"/hoge.dat";

@implementation NCTViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    [self saveData];
    [self loadData];
}

- (void)loadData
{
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *directory = paths[0];
    NSString *filePath = [directory stringByAppendingString:kFileName];

    NSMutableData *data = [NSMutableData dataWithContentsOfFile:filePath];
    NSKeyedUnarchiver *decoder = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
    NSArray *dataArray = [decoder decodeObjectForKey:@"array"];
    [decoder finishDecoding];

    NSLog(@"Data array: %@", dataArray);
}

- (void)saveData
{
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *directory = paths[0];
    NSString *filePath  = [directory stringByAppendingString:kFileName];

    NSMutableArray *dataArray = [NSMutableArray array];
    for (int i = 0; i < 5; i++) {
        NCTSample *data = [[NCTSample alloc] init];
        data.name = [NSString stringWithFormat:@"My name is Bob%d", i];
        data.age  = i;
        [dataArray addObject:data];
    }

    NSMutableData *data = [NSMutableData data];
    NSKeyedArchiver *encoder = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
    [encoder encodeObject:dataArray forKey:@"array"];
    [encoder finishEncoding];

    [data writeToFile:filePath atomically:YES];
}

@end

39
37
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
39
37