typedef 枚举类型作为 NSDictionary 的键?
Posted
技术标签:
【中文标题】typedef 枚举类型作为 NSDictionary 的键?【英文标题】:typedef enum type as key to NSDictionary? 【发布时间】:2009-06-18 18:14:38 【问题描述】:枚举是否不允许作为 NSMutableDictionary 的键?
当我尝试通过以下方式添加到字典时:
[self.allControllers setObject:aController forKey:myKeyType];
我得到错误:
错误:参数类型不兼容 2 of 'setObject:forKey:'
通常,我使用 NSString 作为我的键名,它不需要强制转换为“id”,但为了使错误消失,我必须这样做。这里的强制转换是正确的行为还是将枚举作为键是一个坏主意?
我的枚举定义为:
typedef enum tagMyKeyType
firstItemType = 1,
secondItemType = 2
MyKeyType;
字典是这样定义和正确分配的:
NSMutableDictionary *allControllers;
allControllers = [[NSMutableDictionary alloc] init];
【问题讨论】:
为什么不直接使用数组? 【参考方案1】:您可以将枚举存储在 NSNumber 中。 (枚举不只是整数吗?)
[allControllers setObject:aController forKey:[NSNumber numberWithInt: firstItemType]];
在 Cocoa 中,经常使用 const NSStrings。在 .h 中,您可以声明如下内容:
NSString * const kMyTagFirstItemType;
NSString * const kMyTagSecondtItemType;
然后在 .m 文件中放置
NSString * const kMyTagFirstItemType = @"kMyTagFirstItemType";
NSString * const kMyTagSecondtItemType = @"kMyTagSecondtItemType";
然后你可以将它用作字典中的键。
[allControllers setObject:aController forKey:kMyTagFirstItemType];
【讨论】:
我想你想在这里的 .h 文件中使用extern
关键字,对吗?
您也可以使用 FOUNDATION_EXPORT
作为关键字,我认为它也可以被 typedef 到 extern
。【参考方案2】:
这是一个老问题,但可以更新以使用更现代的语法。首先,从 ios 6 开始,Apple 建议将枚举定义为:
typedef NS_ENUM(NSInteger, MyEnum)
MyEnumValue1 = -1, // default is 0
MyEnumValue2, // = 0 Because the last value is -1, this auto-increments to 0
MyEnumValue3 // which means, this is 1
;
然后,由于我们在内部将枚举表示为NSInteger
s,因此我们可以将它们装箱到NSNumber
s 中以存储为字典的键。
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
// set the value
dictionary[@(MyEnumValue1)] = @"test";
// retrieve the value
NSString *value = dictionary[@(MyEnumValue1)];
编辑:如何为此目的创建单例字典
通过这种方法,您可以创建一个单例字典来帮助解决这个问题。在您拥有的任何文件的顶部,您可以使用:
static NSDictionary *enumTranslations;
然后在您的init
或viewDidLoad
中(如果您在 UI 控制器中执行此操作),您可以执行此操作:
static dispatch_once_t onceToken;
// this, in combination with the token above,
// will ensure that the block is only invoked once
dispatch_async(&onceToken, ^
enumTranslations = @
@(MyEnumValue1): @"test1",
@(MyEnumValue2): @"test2"
// and so on
;
);
// alternatively, you can do this as well
static dispatch_once_t onceToken;
// this, in combination with the token above,
// will ensure that the block is only invoked once
dispatch_async(&onceToken, ^
NSMutableDictionary *mutableDict = [NSMutableDictionary dictionary];
mutableDict[@(MyEnumValue1)] = @"test1";
mutableDict[@(MyEnumValue2)] = @"test2";
// and so on
enumTranslations = mutableDict;
);
如果您希望此字典在外部可见,请将静态声明移动到您的标头 (.h
) 文件中。
【讨论】:
【参考方案3】:不,你不能。查看方法签名:id
指定一个对象。枚举类型是标量。您不能从一个转换到另一个并期望它正常工作。你必须使用一个对象。
【讨论】:
这是真的。但是,您可以将枚举值包装在 NSNumber 中并将其用作键。以上是关于typedef 枚举类型作为 NSDictionary 的键?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Angular 中定义枚举类型以不违反 tslint typedef 规则