【发布时间】:2010-11-14 07:11:19
【问题描述】:
我需要创建一个字典/哈希图,其中
- 键是枚举
- 值是
NSObject的某个子类
NSDictionary 在这里不起作用(枚举不符合NSCopying)。
我也许可以在这里使用CFDictionaryRef,但我想知道是否有其他方法可以实现这一点。
【问题讨论】:
标签: objective-c cocoa dictionary enums hashtable
我需要创建一个字典/哈希图,其中
NSObject 的某个子类
NSDictionary 在这里不起作用(枚举不符合NSCopying)。
我也许可以在这里使用CFDictionaryRef,但我想知道是否有其他方法可以实现这一点。
【问题讨论】:
标签: objective-c cocoa dictionary enums hashtable
由于枚举是整数,因此您可以将枚举包装在 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 的建议,在枚举结果不是整数的情况下使用 NSValue 可能会更好(例如当 -fshort-enums 发挥作用时,这不应该因为您可能会破坏与基金会)。
NSValue *value = [NSValue value: &myEnum withObjCType: @encode(enum ETest)];
这里不会增加太多内容,但会为您提供一般的“我想在集合类中使用
请注意,使用现代编译器您可以告诉enums to use a fixed underlying type。这意味着您可以控制用于枚举的存储空间,但由于上述解决方案是通用的,即使您知道这一点,它仍然适用。
【讨论】:
NSValue,但出现错误:stackoverflow.com/questions/6130315/…
进一步扩展 Graham Lee 的建议...
您可以使用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
接下来我们将为 NSMutableDictionary 添加“枚举 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];
根据您使用枚举访问字典的次数,这可能会大大降低代码的可读性。
【讨论】:
-[NSDictionary objectForETest:] :-/
[object class]。这将使装箱/拆箱过程更加宜居。
枚举不符合 NSCopying
这是轻描淡写的;枚举不“符合”任何东西,因为它们不是对象;它们是可与整数互换的原始 C 值。这就是它们不能用作键的真正原因。 NSDictionary 的键和值需要是对象。但由于枚举是整数,您可以将它们包装到 NSNumber 对象中。这可能是最简单的选择。
另一个选项,如果枚举从 0 到某个数字是连续的(即您没有手动设置任何值),您可以使用NSArray,其中索引表示键枚举的值。 (任何“缺失”的条目都必须填写NSNull。)
【讨论】:
类别方法有其自己的用途,但较新的盒装表达式(例如@(FOO))应该为您处理类型转换。它通过在将枚举用作键时显式装箱来非常透明地工作。
【讨论】: