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
;

然后,由于我们在内部将枚举表示为NSIntegers,因此我们可以将它们装箱到NSNumbers 中以存储为字典的键。

NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];

// set the value
dictionary[@(MyEnumValue1)] = @"test";

// retrieve the value
NSString *value = dictionary[@(MyEnumValue1)];

编辑:如何为此目的创建单例字典

通过这种方法,您可以创建一个单例字典来帮助解决这个问题。在您拥有的任何文件的顶部,您可以使用:

static NSDictionary *enumTranslations;

然后在您的initviewDidLoad 中(如果您在 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 的键?的主要内容,如果未能解决你的问题,请参考以下文章

在结构中使用 typedef 枚举并避免类型混合警告

如何在 Angular 中定义枚举类型以不违反 tslint typedef 规则

第6课 类型别名和强枚举类型

C语言第十二章:结构体共用体(联合体)枚举typedef

ObjectiveC: 变量和数据类型:初始化方法外部/静态变量枚举类型typedef类型转换位运算符

黑马程序员C语言基础(第八天)复合类型(自定义类型)共用体(联合体)枚举 typedef