Cocoa:带枚举键的字典?

时间:2009-07-27 08:44:16

标签: objective-c cocoa dictionary enums hashtable

我需要在

中创建一个字典/ hashmap
  • 键是枚举
  • 值是NSObject
  • 的子类

NSDictionary在此不起作用(枚举不符合NSCopying)。

我或许可以在这里使用CFDictionaryRef,但我想知道是否还有其他方法可以实现这一点。

5 个答案:

答案 0 :(得分:29)

由于枚举是整数,因此可以将枚举包装在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]; 

答案 1 :(得分:28)

根据VoidPointer的建议,当枚举结果不是整数时(例如NSValue正在播放时),最好使用-fshort-enums,这应该永远不会像你一样可能会破坏与基金会的兼容性。)

NSValue *value = [NSValue value: &myEnum withObjCType: @encode(enum ETest)];

这不会在这里增加太多但是给你一般的“我想在收集类中使用<非ObjC类型的名称>”技术。

请注意,使用现代编译器,您可以告诉enums to use a fixed underlying type。这意味着您可以控制用于枚举的存储空间,但由于上述解决方案是通用的,因此即使您知道这一点,它仍然适用。

答案 2 :(得分:9)

进一步延伸Graham Lee的建议......

您可以使用objective-c category向NSMutableDictionary添加一个方法,该方法允许您使用非NSObject类型的键添加值。这可以使您的代码免于包装/解包语法。

再次,假设

enum ETest { FOO, BAR };

首先,我们在NSValue中添加一个conince构造函数:

@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

接下来,我们将为NSMutableDictionary添加'enum ETest'支持

@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];

根据您使用enum访问字典的程度,这可能会使代码的可读性大大降低。

答案 3 :(得分:7)

  

枚举不符合NSCopying

这是轻描淡写;枚举不会“符合”任何东西,因为它们不是对象;它们是原始C值,可与整数互换。这就是他们不能用作钥匙的真正原因。 NSDictionary的键和值必须是对象。但由于枚举是整数,因此您可以将它们包装到NSNumber个对象中。这可能是最简单的选择。

另一个选项,如果枚举从0到某个数字是连续的(即你没有手动设置任何值),那么你可以使用NSArray,其中索引代表关键枚举的值。 (任何“缺失”条目都必须填充NSNull。)

答案 4 :(得分:2)

我也喜欢类别方法,也可能在我的情况下实现这一点。随着新的文字/拳击表达无论它被称为什么,将使用@(FOO)为你照顾拳击?

我认为通过在将枚举用作键时明确地装入枚举,它会非常透明地工作。