Cocoa:带有枚举键的字典?
我需要创建一个字典/哈希图,其中
- 键是枚举,
- 值是
NSObject
的一些子类
NSDictionary
在这里不起作用(枚举不符合 NSCopying )。
我也许可以在这里使用 CFDictionaryRef,但我想知道是否有其他方法可以实现此目的。
I need to create a dictionary/hashmap where the
- Keys are enums
- Values are some subclass of
NSObject
NSDictionary
won't work here (enums don't conform to NSCopying
).
I could perhaps use a CFDictionaryRef
here, but I'd like to know if is there any other way to achieve this.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
由于枚举是整数,因此您可以将枚举包装在 NSNumber 中。 当您向地图添加/检索某些内容时,您将枚举传递给 NSNumber 构造函数...
假设您有一个像这样的枚举...
您可以在 NSDictionary 中使用它,如下所示...
Since enums are integers, you can wrap the enum in an NSNumber. When you add/retreive something to/from the map, you pass the enum to the NSNumber constructor...
Assuming you've got an enum like...
You can use it in an NSDictionary like this...
根据 VoidPointer 的建议,当枚举结果不是整数时(例如当使用
-fshort-enums
时,应该使用NSValue
可能会更好)永远不要,因为你可能会破坏与基金会的兼容性)。这里不会添加太多内容,但会为您提供一般的“我想在集合类中使用<非 ObjC 类型的名称>”技术。
请注意,使用现代编译器,您可以告诉枚举使用固定的基础类型。 这意味着您可以控制用于枚举的存储,但由于上述解决方案是通用的,即使您知道这一点,它仍然适用。
With VoidPointer's suggestion, it may be better to use
NSValue
for those times when enums turn out not to be integers (such as when-fshort-enums
is in play, which should be never as you'd probably break compatibility with Foundation).That's not going to add much here but gives you the general "I want to use <name of non-ObjC type> in a collection class" technique.
Notice that with modern compilers you can tell enums to use a fixed underlying type. This means you can control what storage is used for the enum, but as the above solution is general it still applies even when you know this.
进一步扩展 Graham Lee 的建议...
您可以使用 Objective-c category 以便向 NSMutableDictionary 添加一个方法,该方法允许您使用非 NSObject 类型的键添加值。 这使您的代码不受包装/展开语法的影响。
再次,假设
首先,我们向 NSValue 添加一个令人信服的构造函数:
接下来,我们将为 NSMutableDictionary 添加“enum ETest”支持,
因此原始示例可以转换为
根据您使用枚举来访问字典的程度,这可能会缓解你的代码的可读性相当高。
Further extending on the suggestion from Graham Lee...
You could use an objective-c category in order to add a method to NSMutableDictionary that allows you to add a value with a key of your non NSObject type. This keeps your code free from the wrapping/unwrapping syntax.
Again, assuming
First, we're adding a convince constructor to NSValue:
Next we'll add 'enum ETest' support to NSMutableDictionary
The original Example can thus be transformed to
Depending on how much you use your enum to access the dictionary this may ease readability of your code quite a bit.
这是轻描淡写的说法; 枚举不“符合”任何事物,因为它们不是对象; 它们是原始 C 值,可以与整数互换。 这就是它们不能用作密钥的真正原因。
NSDictionary
的键和值必须是对象。 但由于枚举是整数,因此您可以将它们包装到NSNumber
对象中。 这可能是最简单的选择。另一种选择是,如果枚举从 0 到某个数字是连续的(即您没有手动设置任何值),则可以使用 NSArray,其中索引表示键枚举的值。 (任何“缺失”的条目都必须用
NSNull
填充。)This is an understatement; enums do not "conform" to anything as they are not objects; they are primitive C values which are interchangeable with integers. That's the real reason why they can't be used as keys. The keys and values of
NSDictionary
need to be objects. But since enums are integers, you can just wrap them intoNSNumber
objects. This is probably the simplest option.Another option, if the enums are contiguous from 0 up to some number (i.e. you didn't set any values manually), is that you can use an
NSArray
where the index represents the key enum's value. (Any "missing" entries would have to be filled withNSNull
.)类别方法有其自己的用途,但较新的装箱表达式(例如
@(FOO)
)应该为您处理类型转换。 当使用枚举作为键时,它通过显式地装箱来非常透明地工作。The category approach has its own uses, but the newer boxed expressions (e.g.
@(FOO)
) should take care of type conversion for you. It works very transparently by explicitly boxing the enum when using it as a key.