Ric*_*aez 15 c enums objective-c
是否有一种优雅的方式来获取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.
Run Code Online (Sandbox Code Playgroud)
Sul*_*han 17
不幸的是,C枚举(NS_ENUM宏是一个生成器)相当简单,没有反射.
如果您的枚举值是连续的,则使用限制值获取项目数很简单:
typedef NS_ENUM(NSInteger, MyEnum) {
MyEnumA = 0,
MyEnumB,
MyEnumC,
MyEnumMax
};
NSUInteger numItems = MyNumMax;
Run Code Online (Sandbox Code Playgroud)
但是,这不是一个理想的解决方案,因为当您编写a时switch,如果您不添加case MyEnumMax:(或default:),则会收到警告.
那么您最好的选择是为每个枚举创建信息函数:
typedef NS_ENUM(NSInteger, MyEnum) {
MyEnumA = 0,
MyEnumB = 2,
MyEnumC = 4,
};
NSUInteger MyEnumSize() {
return 3;
}
Run Code Online (Sandbox Code Playgroud)
您还可以使用一些高级宏技术(如X-macro)动态生成此函数.
大警告:X-macro不简单,不易读,但功能强大.示例如下:
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();
Run Code Online (Sandbox Code Playgroud)
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];
}
Run Code Online (Sandbox Code Playgroud)
用法
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);
}
Run Code Online (Sandbox Code Playgroud)
现在,您可以修改/添加/删除标题中的值,所有功能都将自动更新.