获得NS_ENUM项目数量的优雅方式

是否有一种优雅的方式来获取NS_ENUM中的项目总数? 而且最大值?


一些例子:

typedef NS_ENUM(NSInteger, MyEnum) { MyEnumA = 0, MyEnumB = 1, MyEnumC = 2 }; // NumberOfItems(MyEnum) -> 3, MaximumValue(MyEnum) -> 2. typedef NS_ENUM(NSInteger, MyEnum) { MyEnumA, MyEnumB, MyEnumC }; // NumberOfItems(MyEnum) -> 3, MaximumValue(MyEnum) -> 2. typedef NS_ENUM(NSInteger, MyEnum) { MyEnumA = 4, MyEnumB, MyEnumC }; // NumberOfItems(MyEnum) -> 3, MaximumValue(MyEnum) -> 6. typedef NS_ENUM(NSInteger, MyEnum) { MyEnumA = 0, MyEnumB = 2, MyEnumC = 4 }; // NumberOfItems(MyEnum) -> 3, MaximumValue(MyEnum) -> 4. 

不幸的是,C枚举( NS_ENUM宏是一个生成器)非常简单,没有reflection。

如果您的枚举值是连续的,则使用限制值获取项目数很简单:

 typedef NS_ENUM(NSInteger, MyEnum) { MyEnumA = 0, MyEnumB, MyEnumC, MyEnumMax }; NSUInteger numItems = MyNumMax; 

但是,这不是一个理想的解决方案,因为当您编写switch ,如果您不添加case MyEnumMax:default: case MyEnumMax: ,您将收到警告。

那么你最好的选择是为每个枚举创建信息函数:

 typedef NS_ENUM(NSInteger, MyEnum) { MyEnumA = 0, MyEnumB = 2, MyEnumC = 4, }; NSUInteger MyEnumSize() { return 3; } 

您还可以使用一些高级宏技术(如X-macro)动态生成此函数。

大警告:X-macro不简单,不易读,但function强大。 示例如下:

MyEnum.h

 #define MY_ENUM_DEFINITIONS \ NS_ENUM_X_VALUE(MyEnumA, = 0) \ NS_ENUM_X_VALUE(MyEnumB,) \ NS_ENUM_X_VALUE(MyEnumC, = 4) #define NS_ENUM_X_VALUE(__NAME__, __INT_VALUE__) __NAME__ __INT_VALUE__, typedef NS_ENUM(NSInteger, MyEnum) { MY_ENUM_DEFINITIONS }; #undef NS_ENUM_X_VALUE NSString * NSStringFromMyEnum(MyEnum value); NSArray * MyEnumValues(); NSUInteger MyEnumSize(); NSUInteger MyEnumMin(); NSUInteger MyEnumMax(); 

MyEnum.m

 #define NS_ENUM_X_VALUE(__NAME__, __INT_VALUE__) [__NAME__] = @#__NAME__, static NSString* MyEnumStringTable[] = { MY_ENUM_DEFINITIONS }; #undef NS_ENUM_X_VALUE NSString * NSStringFromMyEnum(MyEnum value) { return MyEnumStringTable[value]; } #define NS_ENUM_X_VALUE(__NAME__, __INT_VALUE__) @(__NAME__), static NSOrderedSet * MyEnumValueSet() { static NSOrderedSet *valueSet = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ valueSet = [[NSOrderedSet alloc] initWithObjects: MY_ENUM_DEFINITIONS nil]; }); return valueSet; } #undef NS_ENUM_X_VALUE NSArray *MyEnumValues() { return [MyEnumValueSet() array]; } NSUInteger MyEnumSize() { return MyEnumValueSet().count; } NSUInteger MyEnumMin() { return [MyEnumValueSet().firstObject unsignedIntegerValue]; } NSUInteger MyEnumMax() { return [MyEnumValueSet().lastObject unsignedIntegerValue]; } 

用法

 NSLog(@"MyEnum size: %@", @(MyEnumSize())); NSLog(@"MyEnum min: %@", @(MyEnumMin())); NSLog(@"MyEnum max: %@", @(MyEnumMax())); NSLog(@"MyEnumC value to string: %@", NSStringFromMyEnum(MyEnumC)); for (NSNumber *value in MyEnumValues()) { NSLog(@"Value listing: %@ => %@", NSStringFromMyEnum([value unsignedIntegerValue]), value); } 

现在,您可以修改/添加/删除标题中的值,所有function都将自动更新。