その後のその後

iOSエンジニア 堤 修一のブログ github.com/shu223

構造体を NSDictionary や NSArray に格納する方法

C言語の構造体をNSDictionary や NSArray、NSUserDefaultsなどに格納する方法、つまりObjective-Cのオブジェクト化する方法についてです。
CGRectとかCGPointを格納するときと同様、NSValueを用います。


例として下記のようなRGBAの色情報を持つ構造体を定義します。

// 構造体の宣言
typedef struct {
	unsigned char r, g, b, a;
} RGBA;


格納する場合は、value:withObjCType: メソッドを使用します。

// 構造体をNSDictinaryに格納する
RGBA rgba = {255,255,255,255};
NSValue *value = [NSValue value:&rgba withObjCType:@encode(RGBA)];
NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:value, @"rgba", nil];

ポイントは、

  • valueには構造体のポインタを渡すことと、
  • withObjectTypeには@encode(RGBA)と、構造体の型情報をエンコードして渡すこと

です。


@encode()って見慣れないですが、「型エンコード」と呼ばれるもので、こちらのアップルのドキュメントによると、

ランタイムシステムを支援するために、コンパイラは各メソッドの戻り型と引数型を文字列にエンコードし、その文字列とメソッドセレクタを関連付けます。また、コンパイラが使用するエンコード方式は他のコンテキストでも便利に使用することができるため、@encode()コンパイラディレクティブを通じて一般に利用できるようになっています。型指定を渡すと、@encode()はその型をエンコードした文字列を返します。

というものです。


取り出す際は、格納先の構造体のポインタをNSValueのgetValueメソッドに渡してやります。

// 構造体をNSDictionaryから取り出す
RGBA rgba;
[(NSValue *)[dic objectForKey:@"rgba"] getValue:&rgba];


参考ページ