3

我正在使用最新的 SDK 开发一个 iOS 应用程序。

我有这个枚举:

typedef enum BoxTypeValues {
    Speed,
    FPS,
    Altitude,
    Location,
    Accuracy
} BoxType;

我想迭代 throw 它的所有值并将它们转换为NSString.

我正在这样做,但它的编码非常硬:

+ (NSArray*)BoxTypeValues
{
    return [NSArray arrayWithObjects:@"Speed", @"FPS", @"Altitude", @"Location",
            @"Accuracy", nil];
}

+ (NSString*)BoxTypeToString:(BoxType)aType
{
    NSString* result = nil;

    switch (aType)
    {
        case Speed:
            result = @"Speed";
            break;
        case FPS:
            result = @"FPS";
            break;
        case Altitude:
            result = @"Altitude";
            break;
        case Location:
            result = @"Location";
            break;
        case Accuracy:
            result = @"Accuracy";
            break;

        default:
            break;
    }
    return result;
}

有什么建议吗?

4

4 回答 4

6

将枚举值转换为字符串是宏可以提供很大帮助的罕见情况之一。例如:

- (NSString*)BoxTypeToString:(BoxType)aType
{
#define CASE(VALUE) case (VALUE): return @( #VALUE )
    switch (aType) {
            CASE(Speed);
            CASE(FPS);
            CASE(Altitude);
            CASE(Location);
            CASE(Accuracy);

        default:
            // should not get here
            assert(0);
            break;
    }
#undef CASE
    return nil;
}

您的BoxTypeValues方法将如下所示:

- (NSArray*)BoxTypeStringValues
{
    return @[
        [self BoxTypeToString:Speed],
        [self BoxTypeToString:FPS],
        [self BoxTypeToString:Altitude],
        [self BoxTypeToString:Location],
        [self BoxTypeToString:Accuracy]
      ];
}

即使在重构操作重命名枚举值之后,这也将继续正常工作。您可能希望为CASE宏提供某种独特的前缀以避免与其他代码冲突。

至于枚举枚举值,除非您可以依赖连续的值并使用标准 for 循环(正如其他人所建议的那样),否则您很不走运。

于 2013-04-04T10:03:36.473 回答
2
  + (NSString*)BoxTypeToString:(BoxType)aType{
    return [BoxTypeValues objectAtIndex:aType];
}

只需修改您的方法,无需使用 switch-case。

于 2013-04-04T10:07:20.693 回答
1

I encountered this problem multiple times. Everyone who saw java enums wants to have this functionality in Obj-C, too.

One of the solutions is to use a class instead of an enum. If you want to go with enums, there is a nice preprocessor technique called X-Macros.

Let's define the values first:

#define BOX_TYPE_DEFINITIONS \
    BOX_TYPE_DEFINITION(Invalid, = 0) \
    BOX_TYPE_DEFINITION(Speed,) \
    BOX_TYPE_DEFINITION(FPS,) \
    BOX_TYPE_DEFINITION(Altitude,) \
    BOX_TYPE_DEFINITION(Location,) \
    BOX_TYPE_DEFINITION(Accuracy,)

Now the enum

#define BOX_TYPE_DEFINITION(name, intValue) name intValue,

typedef enum {
    BOX_TYPE_DEFINITIONS
} BoxType;

#undef BOX_TYPE_DEFINITION

And "to string" function

#define BOX_TYPE_DEFINITION(name, intValue) [name] = @#name, 

NSString* BoxTypeStringTable[] = {
    BOX_TYPE_DEFINITIONS
};

#undef BOX_TYPE_DEFINITION

#define NUM_BOX_TYPES sizeof(BoxTypeStringTable) / sizeof(NSString*)

NSString* NSStringFromBoxType(BoxType type) {
    return BoxTypeStringTable[type];
}

This technique is very powerful for 3 reasons

  1. If you want to add/remove values, you do it in one place only
  2. You have the list of values as a macro and you can generate almost any code which involves all the values.
  3. You can add other attributes to your enum values (are you sure you don't want to use classes?)
于 2013-04-04T10:18:19.153 回答
0

如果您控制枚举并且可以确保它是连续的,那么您可以执行以下操作 - 但显然您现在必须保持最新状态。

typedef NS_ENUM(NSInteger, BoxType) {
  Speed,
  FPS,
  Altitude,
  Location,
  Accuracy
};

NSString * BoxTypeToString(BoxType boxType)
{
  static NSString *types[] = { @"Speed", @"FPS", @"Altitude", @"Location", @"Accuracy" };
  return types[boxType];
}

注意

我已经把它变成了一个单独的 C 函数,因为我真的无法想象有很多场景可以让一个类有充分的理由负责知道如何将枚举转换为字符串:/

于 2013-04-04T10:09:17.013 回答