独自クラスを NSData に変換する : Objective-C プログラミング

PROGRAM


独自クラスを NSData に変換する

Mac OS X や iPhone プログラミングでは、任意のクラスを NSData 型に変換するための NSCoding インターフェイスが用意されています。

このインターフェイスを実装することで、独自実装のクラスであっても、統一的な方法で、インスタンスの内容を NSData 型に変換することが出来るようになります。

NSString や NSDictionary, NSArray といった Foundation クラスの多くが NSCoding を実装しているので、同様の方法で NSData 型に変換することも可能です。

 

NSData への変換方法

まず、変換方法について記しておきます。

NSCoding インターフェイスを実装したクラスのインスタンスは、NSKeyedArchiver や NSKeyedUnarchiver を利用して、NSData 型との相互変換が可能になります。

 

例えば NSCoding を実装した EzCodingTest クラスがあるとして、そのインスタンス aInstance を NSData 型に変換するには、次のようにします。

// NSCoding インターフェイスを利用して NSData* へ変換します。

NSData* data = [NSKeyedArchiver archivedDataWithRootObject:aInstance];

逆に、NSData 型に変換したものを元のインスタンス型に戻す場合は、次のようにします。

// NSCoding インターフェイスを利用して NSData* から元の型に変換します。

EzCodingTest* aInstance = [NSKeyedUnarchiver unarchiveObjectWithData:data];

これで、元の型に変換することが出来ました。

これを利用することで、アプリケーションの設定値を保持する目的で独自クラスを実装したような場合などでも、NSUserDefaults でアプリケーションの設定値を管理する で記した方法で、簡単に値を管理することが可能になります。

なお、NSData 型への変換も、その逆も、どちらとも autorelease の状態でインスタンスが取得されますので、それを属性などに格納して維持したい場合には、代入の際に retain することも忘れないように注意します。

 

NSCoding の実装方法

それでは実際に、NSCoding インターフェイスを実装する方法について記します。

 

例えば、次の属性を持つクラス EzCodingTest があったとします。

属性名 属性の型
name NSString*
score NSInteger
supports NSArray*

単純に実装した場合、次のような感じになります。

// EzCodingTest クラスのインターフェイスです。

@interface EzCodingTest : NSObject

{

NSString* name;

NSInteger score;

NSArray* supports

}

 

これに NSCoding インターフェイスを実装します。

// NSCoding インターフェイスを付加した EzCodingTest クラスのインターフェイスです。

@interface EzCodingTest : NSObject <NSCoding>

{

NSString* name;

NSInteger score;

NSArray* supports

}

その上で、NSCoding インターフェイスで必要な encodeWithCoder: メソッドと initWithCoder: メソッドを実装して行きます。

// 初期化用メソッド(NSData からの変換で使用)

- (id)initWithCoder:(NSCoder*)aDecoder

{

self = [super init];

 

if (self)

{

// ここで aDecoder に格納しておいた値を取得します。

name = [[aDecoder decodeObjectForKey:@"name"] retain];

score = [aDecoder decodeInt32ForKey:@"score"];

supports = [[aDecoder decodeObjectForKey:@"supports"] retain];

}

 

return self;

}

 

// 変換用メソッド(NSData への変換で使用)

- (void)encodeWithCoder:(NSCoder*)aCoder

{

[aCoder encodeObject:name forKey:@"name"];

[aCoder encodeInt32:score forKey:@"score"];

[aCoder encodeObject:supports forKey:@"supports"];

}

このようにすることで、前に述べた NSKeyedArchiver や NSKeyedUnarchiver を利用して、独自に実装したクラスのインスタンスを NSData* に変換することが可能になります。

なお、今回のように初めて NSCoding を実装するクラスではなく、もし親クラスで NSCoding を実装している場合には、必ず [self initWithCoder:aDecoder] や [self encodeWithCoder:aCoder] を実行して、親側の変換も適切に行われるようにします。

[ もどる ]