辞書/ハッシュマップを作成する必要があります。
NSObject
のサブクラスですNSDictionary
はここでは機能しません(列挙型はNSCopying
に準拠していません)。
ここでCFDictionaryRef
を使用することもできますが、これを実現する他の方法があるかどうかを知りたいと思います。
列挙型は整数であるため、列挙型をNSNumberでラップできます。マップに何かを追加/マップから取得するときは、列挙型をNSNumberコンストラクターに渡します...
あなたが次のような列挙型を持っていると仮定します...
enum ETest {
FOO, BAR
};
このようなNSDictionaryで使用できます...
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
[dict setObject: @"Foo!" forKey:[NSNumber numberWithInt: FOO]];
NSLog(@"getting value for FOO -> %@",
[dict objectForKey: [NSNumber numberWithInt: FOO]]);
[dict release];
VoidPointerの提案により、列挙型が整数ではないことが判明した場合(-fshort-enums
が機能している場合など、Foundationとの互換性を損なう可能性があるため、決して使用しないでください)にはNSValue
を使用する方がよい場合があります。
NSValue *value = [NSValue value: &myEnum withObjCType: @encode(enum ETest)];
ここではあまり追加しませんが、一般的な「コレクションクラスで<非ObjCタイプの名前>を使用したい」というテクニックを紹介します。
最新のコンパイラでは、 固定の基になる型を使用する列挙型 と言うことができることに注意してください。これは、列挙型に使用されるストレージを制御できることを意味しますが、上記のソリューションは一般的であるため、これを知っている場合でも適用されます。
グラハム・リーからの提案をさらに拡張します...
NSMutableDictionaryにメソッドを追加して、NSObject以外のタイプのキーを使用して値を追加できるようにするために、objective-c category を使用できます。これにより、コードがラッピング/アンラッピング構文から解放されます。
繰り返しますが、
enum ETest { FOO, BAR };
まず、NSValueに説得力のあるコンストラクターを追加します。
@interface NSValue (valueWithETest)
+(NSValue*) valueWithETest:(enum ETest)etest;
@end
@implementation NSValue (valueWithETest)
+(NSValue*) valueWithETest:(enum ETest)etest
{
return [NSValue value: &etest withObjCType: @encode(enum ETest)];
}
@end
次に、「列挙型ETest」サポートをNSMutableDictionaryに追加します
@interface NSMutableDictionary (objectForETest)
-(void) setObject:(id)anObject forETest:(enum ETest)key;
-(id) objectForETest:(enum ETest)key;
@end
@implementation NSMutableDictionary (objectForETest)
-(void) setObject:(id)anObject forETest:(enum ETest)key
{
[self setObject: anObject forKey:[NSValue valueWithETest:key]];
}
-(id) objectForETest:(enum ETest)key
{
return [self objectForKey:[NSValue valueWithETest:key]];
}
@end
したがって、元の例は次のように変換できます。
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
[dict setObject: @"Bar!" forETest:BAR];
NSLog(@"getting value Bar -> %@", [dict objectForETest: BAR]);
[dict release];
列挙型を使用して辞書にアクセスする量によっては、コードがかなり読みやすくなる場合があります。
列挙型がNSCopyingに準拠していません
これは控えめな表現です。列挙型はオブジェクトではないため、何にも「適合」しません。それらは整数と交換可能なプリミティブC値です。それが、キーとして使用できない本当の理由です。 NSDictionary
のキーと値はオブジェクトである必要があります。ただし、列挙型は整数であるため、列挙型をNSNumber
オブジェクトにラップするだけで済みます。これはおそらく最も簡単なオプションです。
別のオプションは、列挙型が0から特定の数まで連続している場合(つまり、手動で値を設定しなかった場合)、インデックスがキー列挙型の値を表すNSArray
を使用できることです。 (「欠落している」エントリはすべてNSNull
で埋める必要があります。)
私はカテゴリーアプローチも好きで、おそらく私の場合にもこれを実装するでしょう。新しいリテラル/ボクシング式と呼ばれるものでは、@(FOO)を使用してボクシングを処理しますか?
キーとして使用するときに列挙型を明示的にボックス化することで、非常に透過的に機能すると思います。