Cocoa:带枚举键的字典?

Pla*_*mer 24 cocoa enums dictionary hashtable objective-c

我需要创建一个字典/ hashmap

  • 键是枚举
  • 值是一些子类 NSObject

NSDictionary在这里不会工作(枚举不符合NSCopying).

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

Voi*_*ter 30

由于枚举是整数,因此可以将枚举包装在NSNumber中.当您向/从地图添加/返回内容时,将枚举传递给NSNumber构造函数...

假设你有一个像...这样的枚举

enum ETest {
    FOO, BAR
};
Run Code Online (Sandbox Code Playgroud)

你可以在像这样的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]; 
Run Code Online (Sandbox Code Playgroud)


小智 28

使用VoidPointer的建议,最好NSValue在枚举结果不是整数的时候使用(例如-fshort-enums在播放时,这应该永远不会因为你可能会破坏与Foundation的兼容性).

NSValue *value = [NSValue value: &myEnum withObjCType: @encode(enum ETest)];
Run Code Online (Sandbox Code Playgroud)

这不会在这里增加很多但是给你一般的"我想在集合类中使用<非ObjC类型的名称>"技术.

请注意,使用现代编译器,您可以告诉枚举使用固定的基础类型.这意味着您可以控制用于枚举的存储空间,但由于上述解决方案是通用的,因此即使您知道这一点,它仍然适用.


Voi*_*ter 9

进一步扩展Graham Lee的建议......

您可以使用objective-c 类别向NSMutableDictionary添加一个方法,该方法允许您使用非NSObject类型的键添加值.这使您的代码不受包装/解包语法的影响.

再说一次,假设

enum ETest { FOO, BAR };
Run Code Online (Sandbox Code Playgroud)

首先,我们在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
Run Code Online (Sandbox Code Playgroud)

接下来,我们将为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
Run Code Online (Sandbox Code Playgroud)

因此可以将原始示例转换为

NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
[dict setObject: @"Bar!" forETest:BAR];
NSLog(@"getting value Bar -> %@", [dict objectForETest: BAR]);      
[dict release];
Run Code Online (Sandbox Code Playgroud)

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


new*_*cct 7

枚举不符合NSCopying

这是轻描淡写; 枚举不会"符合"任何东西,因为它们不是对象; 它们是原始C值,可与整数互换.这就是他们不能用作钥匙的真正原因.NSDictionary需要作为对象的键和值.但由于枚举是整数,你可以将它们包装成NSNumber对象.这可能是最简单的选择.

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