我需要创建一个字典/ HashMap的其中可可:带有枚举键的字典?
- 键是枚举
- 数值为
NSObject
一些子类
NSDictionary
不会在这里工作(枚举不符合NSCopying
)。
我也许可以在这里使用CFDictionaryRef
,但我想知道是否有任何其他方式来实现这一点。
我需要创建一个字典/ HashMap的其中可可:带有枚举键的字典?
NSObject
一些子类NSDictionary
不会在这里工作(枚举不符合NSCopying
)。
我也许可以在这里使用CFDictionaryRef
,但我想知道是否有任何其他方式来实现这一点。
由于枚举是整数,所以可以将枚举包装在一个NSNumber中。当您添加/ retreive到/从地图上看,你通过枚举到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];
enums don't conform to NSCopying
这是一个保守的;枚举不“符合”任何事物,因为它们不是对象;它们是可与整数互换的原始C值。这就是为什么他们不能用作钥匙的真正原因。 NSDictionary
的键和值需要是对象。但由于枚举是整数,所以可以将它们包装为NSNumber
对象。这可能是最简单的选择。
另一种选择是,如果枚举从0到某个数字连续(即没有手动设置任何值),则可以使用NSArray
,其中索引代表键枚举的值。 (任何“遗漏”项就必须充满NSNull
)
随着VoidPointer的建议,它可能是更好的使用NSValue
对于那些时候,枚举变成不为整数时(如-fshort-enums
是在玩,这应该永远不会像你可能会破坏与基金会的兼容性)。
NSValue *value = [NSValue value: &myEnum withObjCType: @encode(enum ETest)];
那不是要在这里多添加,但给你一般的“我想在集合类使用非ObjC型>的<名”技术。
请注意,现代编译器可以告诉enums to use a fixed underlying type。这意味着你可以控制枚举所使用的存储空间,但是由于上面的解决方案是通用的,即使你知道这一点,它仍然适用。
不错,这确实是一个更好的适合,因为它正是NSValue的。 NSValue是否将指向int的值复制到ctor? – VoidPointer 2009-07-27 13:29:26
好吧,http://cocoadev.com/forums/comments.php?DiscussionID=1169&page=1表示它确实复制:) – VoidPointer 2009-07-27 13:30:54
进一步扩展了从格雷厄姆·李的建议...
你可以使用Objective-C的category以增加的NSMutableDictionary的方法,可以让你与你的非NSObject的类型的键添加值。这使您的代码免于包装/解包语法。
再次,假设
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];
取决于您使用enum访问字典的次数多少,这可能会让您的代码更容易阅读。
我也喜欢类别的方法,也可能会在我的情况下实现这一点。用新的Literals/boxing表达式,无论它叫什么,都会用@(FOO)来照顾你的拳击吗?
我认为它会,如果是这样,通过明确地装箱枚举使用它作为一个关键时非常透明。
谢谢!这工作绝对好:) – PlagueHammer 2009-07-28 04:09:46