枚举值到 NSString (iOS)

发布于 2024-11-15 05:21:56 字数 212 浏览 3 评论 0原文

我有一个包含多个值的枚举:

enum {value1, value2, value3} myValue;

在我的应用程序中的某个点,我希望检查枚举的哪个值现在处于活动状态。我正在使用 NSLog,但我不清楚如何将枚举的当前值(value1/valu2/valu3/等...)显示为 NSLog 的 NSString。

有人吗?

I have an enum holding several values:

enum {value1, value2, value3} myValue;

In a certain point in my app, I wish to check which value of the enum is now active. I'm using NSLog but I'm not clear on how to display the current value of the enum (value1/valu2/valu3/etc...) as a NSString for the NSLog.

Anyone?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(16

若有似无的小暗淡 2024-11-22 05:21:56

我不喜欢将枚举放在堆上,而不提供用于翻译的堆函数。这就是我的想法:

typedef enum {value1, value2, value3} myValue;
#define myValueString(enum) [@[@"value1",@"value2",@"value3"] objectAtIndex:enum]

这使枚举和字符串声明紧密结合在一起,以便在需要时轻松更新。

现在,在代码中的任何位置,您都可以像这样使用枚举/宏:

myValue aVal = value2;
NSLog(@"The enum value is '%@'.", myValueString(aVal));

outputs: The enum value is 'value2'.

为了保证元素索引,您始终可以显式声明起始(或所有)枚举值。

enum {value1=0, value2=1, value3=2};

I didn't like putting the enum on the heap, without providing a heap function for translation. Here's what I came up with:

typedef enum {value1, value2, value3} myValue;
#define myValueString(enum) [@[@"value1",@"value2",@"value3"] objectAtIndex:enum]

This keeps the enum and string declarations close together for easy updating when needed.

Now, anywhere in the code, you can use the enum/macro like this:

myValue aVal = value2;
NSLog(@"The enum value is '%@'.", myValueString(aVal));

outputs: The enum value is 'value2'.

To guarantee the element indexes, you can always explicitly declare the start(or all) enum values.

enum {value1=0, value2=1, value3=2};
我是有多爱你 2024-11-22 05:21:56

这里回答了这个问题:一些关于实现的建议

行是Objective-C正在使用常规的旧Cenum,它只是一组美化的整数。

给定一个像这样的enum

typedef enum { a, b, c } FirstThreeAlpha;

您的方法将如下所示:

- (NSString*) convertToString:(FirstThreeAlpha) whichAlpha {
    NSString *result = nil;

    switch(whichAlpha) {
        case a:
            result = @"a";
            break;
        case b:
            result = @"b";
            break;
        case c:
            result = @"c";
            break;

        default:
            result = @"unknown";
    }

    return result;
}

This is answered here: a few suggestions on implementation

The bottom line is Objective-C is using a regular, old C enum, which is just a glorified set of integers.

Given an enum like this:

typedef enum { a, b, c } FirstThreeAlpha;

Your method would look like this:

- (NSString*) convertToString:(FirstThreeAlpha) whichAlpha {
    NSString *result = nil;

    switch(whichAlpha) {
        case a:
            result = @"a";
            break;
        case b:
            result = @"b";
            break;
        case c:
            result = @"c";
            break;

        default:
            result = @"unknown";
    }

    return result;
}
请恋爱 2024-11-22 05:21:56

我介绍的是我使用的方式,看起来比之前的答案更好。(我认为)

我想用UIImageOrientation来说明,以便于理解。

typedef enum {
    UIImageOrientationUp = 0,            // default orientation, set to 0 so that it always starts from 0
    UIImageOrientationDown,          // 180 deg rotation
    UIImageOrientationLeft,          // 90 deg CCW
    UIImageOrientationRight,         // 90 deg CW
    UIImageOrientationUpMirrored,    // as above but image mirrored along other axis. horizontal flip
    UIImageOrientationDownMirrored,  // horizontal flip
    UIImageOrientationLeftMirrored,  // vertical flip
    UIImageOrientationRightMirrored, // vertical flip
} UIImageOrientation;

创建一个如下方法:

NSString *stringWithUIImageOrientation(UIImageOrientation input) {
    NSArray *arr = @[
    @"UIImageOrientationUp",            // default orientation
    @"UIImageOrientationDown",          // 180 deg rotation
    @"UIImageOrientationLeft",          // 90 deg CCW
    @"UIImageOrientationRight",         // 90 deg CW
    @"UIImageOrientationUpMirrored",    // as above but image mirrored along other axis. horizontal flip
    @"UIImageOrientationDownMirrored",  // horizontal flip
    @"UIImageOrientationLeftMirrored",  // vertical flip
    @"UIImageOrientationRightMirrored", // vertical flip
    ];
    return (NSString *)[arr objectAtIndex:input];
}

您所要做的就是:

  1. 为您的函数命名。

  2. 复制枚举的内容并将其粘贴到NSArray *arr = @[]之间; return (NSString *)[arr objectAtIndex:input];

  3. 放置一些@、"和逗号

  4. 利润!!!!!

I will introduce is the way I use, and it looks better than previous answer.(I thinks)

I would like to illustrate with UIImageOrientation for easy understanding.

typedef enum {
    UIImageOrientationUp = 0,            // default orientation, set to 0 so that it always starts from 0
    UIImageOrientationDown,          // 180 deg rotation
    UIImageOrientationLeft,          // 90 deg CCW
    UIImageOrientationRight,         // 90 deg CW
    UIImageOrientationUpMirrored,    // as above but image mirrored along other axis. horizontal flip
    UIImageOrientationDownMirrored,  // horizontal flip
    UIImageOrientationLeftMirrored,  // vertical flip
    UIImageOrientationRightMirrored, // vertical flip
} UIImageOrientation;

create a method like:

NSString *stringWithUIImageOrientation(UIImageOrientation input) {
    NSArray *arr = @[
    @"UIImageOrientationUp",            // default orientation
    @"UIImageOrientationDown",          // 180 deg rotation
    @"UIImageOrientationLeft",          // 90 deg CCW
    @"UIImageOrientationRight",         // 90 deg CW
    @"UIImageOrientationUpMirrored",    // as above but image mirrored along other axis. horizontal flip
    @"UIImageOrientationDownMirrored",  // horizontal flip
    @"UIImageOrientationLeftMirrored",  // vertical flip
    @"UIImageOrientationRightMirrored", // vertical flip
    ];
    return (NSString *)[arr objectAtIndex:input];
}

All you have to do is :

  1. name your function.

  2. copy contents of enum and paste that between NSArray *arr = @[ and ]; return (NSString *)[arr objectAtIndex:input];

  3. put some @ , " , and comma

  4. PROFIT!!!!

ぺ禁宫浮华殁 2024-11-22 05:21:56

这将由编译器验证,因此您不会意外地混淆索引。

NSDictionary *stateStrings =
 @{
   @(MCSessionStateNotConnected) : @"MCSessionStateNotConnected",
   @(MCSessionStateConnecting) : @"MCSessionStateConnecting",
   @(MCSessionStateConnected) : @"MCSessionStateConnected",
  };
NSString *stateString = [stateStrings objectForKey:@(state)];

var stateStrings: [MCSessionState: String] = [
    .notConnected : "MCSessionState.notConnected",
    .connecting : "MCSessionState.connecting",
    .connected : "MCSessionState.connected"
]
var stateString = stateStrings[MCSessionState.Connected]

更新:一种更快速的方法是使用 CustomStringConvertible 一致性来扩展枚举。此外,通过这种方式,编译器将确保实现底层枚举的每个新添加(而使用数组则不然),因为 switch 语句必须是详尽的。

extension MCSessionState: CustomStringConvertible {
    
    public var description: String {
        switch self {
        case .notConnected:
            return "MCSessionState.notConnected"
        case .connecting:
            return "MCSessionState.connecting"
        case .connected:
            return "MCSessionState.connected"
        @unknown default:
            return "Unknown"
        }
    }
}

// You can use it like this.
var stateString = MCSessionState.connected.description

// Or this.
var stateString = "\(MCSessionState.connected)"

This will be validated by compiler, so you won't mix up indices accidentally.

NSDictionary *stateStrings =
 @{
   @(MCSessionStateNotConnected) : @"MCSessionStateNotConnected",
   @(MCSessionStateConnecting) : @"MCSessionStateConnecting",
   @(MCSessionStateConnected) : @"MCSessionStateConnected",
  };
NSString *stateString = [stateStrings objectForKey:@(state)];

var stateStrings: [MCSessionState: String] = [
    .notConnected : "MCSessionState.notConnected",
    .connecting : "MCSessionState.connecting",
    .connected : "MCSessionState.connected"
]
var stateString = stateStrings[MCSessionState.Connected]

UPDATE: A more Swifty way is to extend the enum with CustomStringConvertible conformance. Also, this way the compiler will safeguard to implement every new addition to the underlying enum (whereas using arrays does not), as switch statements must be exhaustive.

extension MCSessionState: CustomStringConvertible {
    
    public var description: String {
        switch self {
        case .notConnected:
            return "MCSessionState.notConnected"
        case .connecting:
            return "MCSessionState.connecting"
        case .connected:
            return "MCSessionState.connected"
        @unknown default:
            return "Unknown"
        }
    }
}

// You can use it like this.
var stateString = MCSessionState.connected.description

// Or this.
var stateString = "\(MCSessionState.connected)"
星星的軌跡 2024-11-22 05:21:56

我找到了这个网站(下面的例子就来自于此),它为这个问题提供了一个优雅的解决方案。最初的帖子来自这个 StackOverflow 答案

// Place this in your .h file, outside the @interface block
typedef enum {
    JPG,
    PNG,
    GIF,
    PVR
} kImageType;
#define kImageTypeArray @"JPEG", @"PNG", @"GIF", @"PowerVR", nil

...

// Place this in the .m file, inside the @implementation block
// A method to convert an enum to string
-(NSString*) imageTypeEnumToString:(kImageType)enumVal
{
    NSArray *imageTypeArray = [[NSArray alloc] initWithObjects:kImageTypeArray];
    return [imageTypeArray objectAtIndex:enumVal];
}

// A method to retrieve the int value from the NSArray of NSStrings
-(kImageType) imageTypeStringToEnum:(NSString*)strVal
{
    NSArray *imageTypeArray = [[NSArray alloc] initWithObjects:kImageTypeArray];
    NSUInteger n = [imageTypeArray indexOfObject:strVal];
    if(n < 1) n = JPG;
    return (kImageType) n;
}

I found this website (from which the example below is taken) which provides an elegant solution to this problem. The original posting though comes from this StackOverflow answer.

// Place this in your .h file, outside the @interface block
typedef enum {
    JPG,
    PNG,
    GIF,
    PVR
} kImageType;
#define kImageTypeArray @"JPEG", @"PNG", @"GIF", @"PowerVR", nil

...

// Place this in the .m file, inside the @implementation block
// A method to convert an enum to string
-(NSString*) imageTypeEnumToString:(kImageType)enumVal
{
    NSArray *imageTypeArray = [[NSArray alloc] initWithObjects:kImageTypeArray];
    return [imageTypeArray objectAtIndex:enumVal];
}

// A method to retrieve the int value from the NSArray of NSStrings
-(kImageType) imageTypeStringToEnum:(NSString*)strVal
{
    NSArray *imageTypeArray = [[NSArray alloc] initWithObjects:kImageTypeArray];
    NSUInteger n = [imageTypeArray indexOfObject:strVal];
    if(n < 1) n = JPG;
    return (kImageType) n;
}
多情出卖 2024-11-22 05:21:56

如果我可以提供另一种解决方案,该解决方案具有类型检查的额外好处,如果您在转换中缺少枚举值,则会发出警告,提高可读性和简洁性。

对于您给定的示例: typedef enum { value1, value2, value3 } myValue; 您可以这样做:

NSString *NSStringFromMyValue(myValue type) {
    const char* c_str = 0;
#define PROCESS_VAL(p) case(p): c_str = #p; break;
    switch(type) {
            PROCESS_VAL(value1);
            PROCESS_VAL(value2);
            PROCESS_VAL(value3);
    }
#undef PROCESS_VAL

    return [NSString stringWithCString:c_str encoding:NSASCIIStringEncoding];
}

作为旁注。如下声明枚举是一种更好的方法:

typedef NS_ENUM(NSInteger, MyValue) {
    Value1 = 0,
    Value2,
    Value3
}

通过这种方式,您可以获得类型安全(在本例中为 NSInteger),您可以设置预期的枚举偏移量 (= 0) 。

If I can offer another solution that has the added benefit of type checking, warnings if you are missing an enum value in your conversion, readability, and brevity.

For your given example: typedef enum { value1, value2, value3 } myValue; you can do this:

NSString *NSStringFromMyValue(myValue type) {
    const char* c_str = 0;
#define PROCESS_VAL(p) case(p): c_str = #p; break;
    switch(type) {
            PROCESS_VAL(value1);
            PROCESS_VAL(value2);
            PROCESS_VAL(value3);
    }
#undef PROCESS_VAL

    return [NSString stringWithCString:c_str encoding:NSASCIIStringEncoding];
}

As a side note. It is a better approach to declare your enums as so:

typedef NS_ENUM(NSInteger, MyValue) {
    Value1 = 0,
    Value2,
    Value3
}

With this you get type-safety (NSInteger in this case), you set the expected enum offset (= 0).

北斗星光 2024-11-22 05:21:56

在某些情况下,当您需要转换枚举时 -> NSString 和 NSString -> enum 使用 typedef 和 #define (或 const NSStrings)代替 enum 可能会更简单:

typedef NSString *        ImageType;
#define ImageTypeJpg      @"JPG"
#define ImageTypePng      @"PNG"
#define ImageTypeGif      @"GIF"

然后像任何其他 NSString 一样使用“命名”字符串进行操作:

@interface MyData : NSObject
@property (copy, nonatomic) ImageType imageType;
@end

@implementation MyData
- (void)doSomething {
    //...
    self.imageType = ImageTypePng;
    //...
    if ([self.imageType isEqualToString:ImageTypeJpg]) {
        //...
    }
}
@end

In some cases when you need to convert enum -> NSString and NSString -> enum it might be simpler to use a typedef and #define (or const NSStrings) instead of enum:

typedef NSString *        ImageType;
#define ImageTypeJpg      @"JPG"
#define ImageTypePng      @"PNG"
#define ImageTypeGif      @"GIF"

and then just operate with "named" strings as with any other NSString:

@interface MyData : NSObject
@property (copy, nonatomic) ImageType imageType;
@end

@implementation MyData
- (void)doSomething {
    //...
    self.imageType = ImageTypePng;
    //...
    if ([self.imageType isEqualToString:ImageTypeJpg]) {
        //...
    }
}
@end
不及他 2024-11-22 05:21:56

下面的解决方案使用预处理器的字符串化运算符,从而提供更优雅的解决方案。它允许您在一个地方定义枚举术语,以提高对拼写错误的抵御能力。

首先,按以下方式定义枚举。

#define ENUM_TABLE \
X(ENUM_ONE),    \
X(ENUM_TWO)    \

#define X(a)    a
typedef enum Foo {
    ENUM_TABLE
} MyFooEnum;
#undef X

#define X(a)    @#a
NSString * const enumAsString[] = {
    ENUM_TABLE
};
#undef X

现在,按以下方式使用它:

// Usage
MyFooEnum t = ENUM_ONE;
NSLog(@"Enum test - t is: %@", enumAsString[t]);

t = ENUM_TWO;
NSLog(@"Enum test - t is now: %@", enumAsString[t]);

输出:

2014-10-22 13:36:21.344 FooProg[367:60b] Enum test - t is: ENUM_ONE
2014-10-22 13:36:21.344 FooProg[367:60b] Enum test - t is now: ENUM_TWO

@pixel 的答案为我指明了正确的方向。

The solution below uses the preprocessor's stringize operator, allowing for a more elegant solution. It lets you define the enum terms in just one place for greater resilience against typos.

First, define your enum in the following way.

#define ENUM_TABLE \
X(ENUM_ONE),    \
X(ENUM_TWO)    \

#define X(a)    a
typedef enum Foo {
    ENUM_TABLE
} MyFooEnum;
#undef X

#define X(a)    @#a
NSString * const enumAsString[] = {
    ENUM_TABLE
};
#undef X

Now, use it in the following way:

// Usage
MyFooEnum t = ENUM_ONE;
NSLog(@"Enum test - t is: %@", enumAsString[t]);

t = ENUM_TWO;
NSLog(@"Enum test - t is now: %@", enumAsString[t]);

which outputs:

2014-10-22 13:36:21.344 FooProg[367:60b] Enum test - t is: ENUM_ONE
2014-10-22 13:36:21.344 FooProg[367:60b] Enum test - t is now: ENUM_TWO

@pixel's answer pointed me in the right direction.

美人如玉 2024-11-22 05:21:56

您可以使用 X 宏 - 它们非常适合此目的。

好处
1. 实际枚举值和字符串值之间的关系在一处。
2. 您可以稍后在代码中使用常规 switch 语句。

损害
1. 初始设置代码有点迟钝,并且使用了有趣的宏。

代码

#define X(a, b, c) a b,
enum ZZObjectType {
    ZZOBJECTTYPE_TABLE
};
typedef NSUInteger TPObjectType;
#undef X

#define XXOBJECTTYPE_TABLE \
X(ZZObjectTypeZero, = 0, "ZZObjectTypeZero") \
X(ZZObjectTypeOne, = 1, "ZZObjectTypeOne") \
X(ZZObjectTypeTwo, = 2, "ZZObjectTypeTwo") \
X(ZZObjectTypeThree, = 3, "ZZObjectTypeThree") \

+ (NSString*)nameForObjectType:(ZZObjectType)objectType {
#define X(a, b, c) @c, [NSNumber numberWithInteger:a],
    NSDictionary *returnValue = [NSDictionary dictionaryWithObjectsAndKeys:ZZOBJECTTYPE_TABLE nil];
#undef X
    return [returnValue objectForKey:[NSNumber numberWithInteger:objectType]];
}

+ (ZZObjectType)objectTypeForName:(NSString *)objectTypeString {
#define X(a, b, c) [NSNumber numberWithInteger:a], @c,
    NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:ZZOBJECTSOURCE_TABLE nil];
#undef X
    NSUInteger value = [(NSNumber *)[dictionary objectForKey:objectTypeString] intValue];
    return (ZZObjectType)value;
}

现在您可以执行以下操作:

NSString *someString = @"ZZObjectTypeTwo"
ZZObjectType objectType = [[XXObject objectTypeForName:someString] intValue];
switch (objectType) {
    case ZZObjectTypeZero:
        //
        break;
    case ZZObjectTypeOne:
        //
        break;
    case ZZObjectTypeTwo:
        //
        break;
}

此模式自 1960 年代以来就已存在(不是开玩笑!):http://en.wikipedia.org/wiki/X_Macro

You could use X macros - they are perfect for this.

Benefits
1. the relationship between the actual enum value and the string value is in one place.
2. you can use regular switch statements later in your code.

Detriment
1. The initial setup code is a bit obtuse, and uses fun macros.

The code

#define X(a, b, c) a b,
enum ZZObjectType {
    ZZOBJECTTYPE_TABLE
};
typedef NSUInteger TPObjectType;
#undef X

#define XXOBJECTTYPE_TABLE \
X(ZZObjectTypeZero, = 0, "ZZObjectTypeZero") \
X(ZZObjectTypeOne, = 1, "ZZObjectTypeOne") \
X(ZZObjectTypeTwo, = 2, "ZZObjectTypeTwo") \
X(ZZObjectTypeThree, = 3, "ZZObjectTypeThree") \

+ (NSString*)nameForObjectType:(ZZObjectType)objectType {
#define X(a, b, c) @c, [NSNumber numberWithInteger:a],
    NSDictionary *returnValue = [NSDictionary dictionaryWithObjectsAndKeys:ZZOBJECTTYPE_TABLE nil];
#undef X
    return [returnValue objectForKey:[NSNumber numberWithInteger:objectType]];
}

+ (ZZObjectType)objectTypeForName:(NSString *)objectTypeString {
#define X(a, b, c) [NSNumber numberWithInteger:a], @c,
    NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:ZZOBJECTSOURCE_TABLE nil];
#undef X
    NSUInteger value = [(NSNumber *)[dictionary objectForKey:objectTypeString] intValue];
    return (ZZObjectType)value;
}

Now you can do:

NSString *someString = @"ZZObjectTypeTwo"
ZZObjectType objectType = [[XXObject objectTypeForName:someString] intValue];
switch (objectType) {
    case ZZObjectTypeZero:
        //
        break;
    case ZZObjectTypeOne:
        //
        break;
    case ZZObjectTypeTwo:
        //
        break;
}

This pattern has been around since the 1960's (no kidding!): http://en.wikipedia.org/wiki/X_Macro

晌融 2024-11-22 05:21:56

这是一个即插即用的解决方案,您可以通过简单复制和粘贴现有定义来扩展它。

我希望你们都觉得它很有用,就像我发现许多其他 StackOverflow 解决方案很有用一样。

- (NSString*) enumItemNameForPrefix:(NSString*)enumPrefix item:(int)enumItem {
NSString* enumList = nil;
if ([enumPrefix isEqualToString:@"[Add Your Enum Name Here"]) {
    // Instructions:
    // 1) leave all code as is (it's good reference and won't conflict)
    // 2) add your own enums below as follows:
    //    2.1) duplicate the LAST else block below and add as many enums as you like
    //    2.2) Copy then Paste your list, including carraige returns
    //    2.3) add a back slash at the end of each line to concatenate the broken string
    // 3) your are done.
}
else if ([enumPrefix isEqualToString:@"ExampleNonExplicitType"]) {
    enumList = @" \
    ExampleNonExplicitTypeNEItemName1, \
    ExampleNonExplicitTypeNEItemName2, \
    ExampleNonExplicitTypeNEItemName3 \
    ";
}
else if ([enumPrefix isEqualToString:@"ExampleExplicitAssignsType"]) {
    enumList = @" \
    ExampleExplicitAssignsTypeEAItemName1 = 1, \
    ExampleExplicitAssignsTypeEAItemName2 = 2, \
    ExampleExplicitAssignsTypeEAItemName3 = 4 \
    ";
}
else if ([enumPrefix isEqualToString:@"[Duplicate and Add Your Enum Name Here #1"]) {
    // Instructions:
    // 1) duplicate this else block and add as many enums as you like
    // 2) Paste your list, including carraige returns
    // 3) add a back slash at the end of each line to continue/concatenate the broken string
    enumList = @" \
    [Replace only this line: Paste your Enum Definition List Here] \
    ";
}

// parse it
int implicitIndex = 0;
NSString* itemKey = nil;
NSString* itemValue = nil;
NSArray* enumArray = [enumList componentsSeparatedByString:@","];
NSMutableDictionary* enumDict = [[[NSMutableDictionary alloc] initWithCapacity:enumArray.count] autorelease];

for (NSString* itemPair in enumArray) {
    NSArray* itemPairArray = [itemPair componentsSeparatedByString:@"="];
    itemValue = [[itemPairArray objectAtIndex:0] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
    itemKey = [NSString stringWithFormat:@"%d", implicitIndex];
    if (itemPairArray.count > 1)
        itemKey = [[itemPairArray lastObject] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
    [enumDict setValue:itemValue forKey:itemKey];
    implicitIndex++;
}

// return value with or without prefix
NSString* withPrefix = [enumDict valueForKey:[NSString stringWithFormat:@"%d", enumItem]];
NSString* withoutPrefix = [withPrefix stringByReplacingOccurrencesOfString:enumPrefix withString:@""];
NSString* outValue = (0 ? withPrefix : withoutPrefix);
if (0) NSLog(@"enum:%@ item:%d retVal:%@ dict:%@", enumPrefix, enumItem, outValue, enumDict);
return outValue;
}

以下是示例声明:

typedef enum _type1 {
ExampleNonExplicitTypeNEItemName1, 
ExampleNonExplicitTypeNEItemName2, 
ExampleNonExplicitTypeNEItemName3
} ExampleNonExplicitType;

typedef enum _type2 {
ExampleExplicitAssignsTypeEAItemName1 = 1, 
ExampleExplicitAssignsTypeEAItemName2 = 2, 
ExampleExplicitAssignsTypeEAItemName3 = 4
} ExampleExplicitAssignsType;

这是一个示例调用:

NSLog(@"EXAMPLE:  type1:%@  type2:%@ ", [self enumItemNameForPrefix:@"ExampleNonExplicitType" item:ExampleNonExplicitTypeNEItemName2], [self enumItemNameForPrefix:@"ExampleExplicitAssignsType" item:ExampleExplicitAssignsTypeEAItemName3]);

Enjoy!
;-)

Here is a plug-and-play solution that you can extend with a simple copy and paste of your EXISTING definitions.

I hope you all find it useful, as I have found useful so many other StackOverflow solutions.

- (NSString*) enumItemNameForPrefix:(NSString*)enumPrefix item:(int)enumItem {
NSString* enumList = nil;
if ([enumPrefix isEqualToString:@"[Add Your Enum Name Here"]) {
    // Instructions:
    // 1) leave all code as is (it's good reference and won't conflict)
    // 2) add your own enums below as follows:
    //    2.1) duplicate the LAST else block below and add as many enums as you like
    //    2.2) Copy then Paste your list, including carraige returns
    //    2.3) add a back slash at the end of each line to concatenate the broken string
    // 3) your are done.
}
else if ([enumPrefix isEqualToString:@"ExampleNonExplicitType"]) {
    enumList = @" \
    ExampleNonExplicitTypeNEItemName1, \
    ExampleNonExplicitTypeNEItemName2, \
    ExampleNonExplicitTypeNEItemName3 \
    ";
}
else if ([enumPrefix isEqualToString:@"ExampleExplicitAssignsType"]) {
    enumList = @" \
    ExampleExplicitAssignsTypeEAItemName1 = 1, \
    ExampleExplicitAssignsTypeEAItemName2 = 2, \
    ExampleExplicitAssignsTypeEAItemName3 = 4 \
    ";
}
else if ([enumPrefix isEqualToString:@"[Duplicate and Add Your Enum Name Here #1"]) {
    // Instructions:
    // 1) duplicate this else block and add as many enums as you like
    // 2) Paste your list, including carraige returns
    // 3) add a back slash at the end of each line to continue/concatenate the broken string
    enumList = @" \
    [Replace only this line: Paste your Enum Definition List Here] \
    ";
}

// parse it
int implicitIndex = 0;
NSString* itemKey = nil;
NSString* itemValue = nil;
NSArray* enumArray = [enumList componentsSeparatedByString:@","];
NSMutableDictionary* enumDict = [[[NSMutableDictionary alloc] initWithCapacity:enumArray.count] autorelease];

for (NSString* itemPair in enumArray) {
    NSArray* itemPairArray = [itemPair componentsSeparatedByString:@"="];
    itemValue = [[itemPairArray objectAtIndex:0] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
    itemKey = [NSString stringWithFormat:@"%d", implicitIndex];
    if (itemPairArray.count > 1)
        itemKey = [[itemPairArray lastObject] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
    [enumDict setValue:itemValue forKey:itemKey];
    implicitIndex++;
}

// return value with or without prefix
NSString* withPrefix = [enumDict valueForKey:[NSString stringWithFormat:@"%d", enumItem]];
NSString* withoutPrefix = [withPrefix stringByReplacingOccurrencesOfString:enumPrefix withString:@""];
NSString* outValue = (0 ? withPrefix : withoutPrefix);
if (0) NSLog(@"enum:%@ item:%d retVal:%@ dict:%@", enumPrefix, enumItem, outValue, enumDict);
return outValue;
}

Here are the example declarations:

typedef enum _type1 {
ExampleNonExplicitTypeNEItemName1, 
ExampleNonExplicitTypeNEItemName2, 
ExampleNonExplicitTypeNEItemName3
} ExampleNonExplicitType;

typedef enum _type2 {
ExampleExplicitAssignsTypeEAItemName1 = 1, 
ExampleExplicitAssignsTypeEAItemName2 = 2, 
ExampleExplicitAssignsTypeEAItemName3 = 4
} ExampleExplicitAssignsType;

Here is an example call:

NSLog(@"EXAMPLE:  type1:%@  type2:%@ ", [self enumItemNameForPrefix:@"ExampleNonExplicitType" item:ExampleNonExplicitTypeNEItemName2], [self enumItemNameForPrefix:@"ExampleExplicitAssignsType" item:ExampleExplicitAssignsTypeEAItemName3]);

Enjoy!
;-)

俏︾媚 2024-11-22 05:21:56

下面是一个对 Objective-C 友好的 Enum Struct 示例,如果您需要在用 Objective-C 编写的旧项目中使用 Swift 代码的话。

示例:

contentType.文件名。 toString()

返回“文件名”


内容类型.文件名。 原始值

返回 Int 值,1 (因为它是结构中的第二项)

@objc enum contentType:Int {

    //date when content was created [RFC2183]
    case creationDate

    //name to be used when creating file    [RFC2183]
    case filename

    //whether or not processing is required [RFC3204]
    case handling

    //date when content was last modified   [RFC2183]
    case modificationDate

    //original field name in form   [RFC7578]
    case name

    //Internet media type (and parameters) of the preview output desired from a processor by the author of the MIME content [RFC-ietf-appsawg-text-markdown-12]
    case previewType

    //date when content was last read   [RFC2183]
    case readDate

    //approximate size of content in octets [RFC2183]
    case size

    //type or use of audio content  [RFC2421]
    case voice

    func toString() -> String {
        switch self {
        case .creationDate:
            return "creation-date"
        case .filename:
            return "filename"
        case .handling:
            return "handling"
        case .modificationDate:
            return "modification-date"
        case .name:
            return "name"
        case .previewType:
            return "preview-type"
        case .readDate:
                return "read-date"
        case .size:
            return "size"
        case .voice:
            return "voice"
        }
    }//eom
}//eo-enum

Below is a example of Enum Struct that is Objective-C friendly in the event you need to use Swift Code in Legacy projects written in Objective-C.

Example:

contentType.filename. toString()

returns "filename"


contentType.filename. rawValue

returns the Int Value, 1 (since its the second item on struct)

@objc enum contentType:Int {

    //date when content was created [RFC2183]
    case creationDate

    //name to be used when creating file    [RFC2183]
    case filename

    //whether or not processing is required [RFC3204]
    case handling

    //date when content was last modified   [RFC2183]
    case modificationDate

    //original field name in form   [RFC7578]
    case name

    //Internet media type (and parameters) of the preview output desired from a processor by the author of the MIME content [RFC-ietf-appsawg-text-markdown-12]
    case previewType

    //date when content was last read   [RFC2183]
    case readDate

    //approximate size of content in octets [RFC2183]
    case size

    //type or use of audio content  [RFC2421]
    case voice

    func toString() -> String {
        switch self {
        case .creationDate:
            return "creation-date"
        case .filename:
            return "filename"
        case .handling:
            return "handling"
        case .modificationDate:
            return "modification-date"
        case .name:
            return "name"
        case .previewType:
            return "preview-type"
        case .readDate:
                return "read-date"
        case .size:
            return "size"
        case .voice:
            return "voice"
        }
    }//eom
}//eo-enum
骄傲 2024-11-22 05:21:56

这是一个老问题,但是如果您有一个不连续的枚举,请使用字典文字而不是数组:

typedef enum {
    value1 = 0,
    value2 = 1,
    value3 = 2,

    // beyond value3
    value1000 = 1000,
    value1001
} MyType;

#define NSStringFromMyType( value ) \
( \
    @{ \
        @( value1 )    : @"value1", \
        @( value2 )    : @"value2", \
        @( value3 )    : @"value3", \
        @( value1000 ) : @"value1000", \
        @( value1001 ) : @"value1001", \
    } \
    [ @( value ) ] \
)

This is an old question, but if you have a non contiguous enum use a dictionary literal instead of an array:

typedef enum {
    value1 = 0,
    value2 = 1,
    value3 = 2,

    // beyond value3
    value1000 = 1000,
    value1001
} MyType;

#define NSStringFromMyType( value ) \
( \
    @{ \
        @( value1 )    : @"value1", \
        @( value2 )    : @"value2", \
        @( value3 )    : @"value3", \
        @( value1000 ) : @"value1000", \
        @( value1001 ) : @"value1001", \
    } \
    [ @( value ) ] \
)
清引 2024-11-22 05:21:56

假设要求是枚举语言列表。

将其添加到 .h 文件中

typedef NS_ENUM(NSInteger, AvailableLanguage) {
  ENGLISH,
  GERMAN,
  CHINENSE
};

现在,在 .m 文件中只需创建一个数组,例如,

// Try to use the same naming convention throughout. 
// That is, adding ToString after NS_ENUM name;

NSString* const AvailableLanguageToString[] = {
  [ENGLISH] = @"English",
  [GERMAN]  = @"German",
  [CHINESE] = @"Chinese"
};

就是这样。现在您可以使用 easy 枚举并使用数组获取枚举字符串。例如,

- (void) setPreferredLanguage:(AvailableLanguage)language {
  // this will get the NSString* for the language.
  self.preferredLanguage = AvailableLanguageToString[language];
}

因此,此模式取决于 NS_ENUM 和同伴 ToString 数组的可接受的命名约定。尝试完全遵循这个惯例,它就会变得自然。

Suppose requirement is to enumerate list of languages.

Add this to .h file

typedef NS_ENUM(NSInteger, AvailableLanguage) {
  ENGLISH,
  GERMAN,
  CHINENSE
};

Now, in .m file simply create an array like,

// Try to use the same naming convention throughout. 
// That is, adding ToString after NS_ENUM name;

NSString* const AvailableLanguageToString[] = {
  [ENGLISH] = @"English",
  [GERMAN]  = @"German",
  [CHINESE] = @"Chinese"
};

Thats it. Now you can use enum with easy and get string for enums using array. For example,

- (void) setPreferredLanguage:(AvailableLanguage)language {
  // this will get the NSString* for the language.
  self.preferredLanguage = AvailableLanguageToString[language];
}

Thus, this pattern depends on accepted naming convention of NS_ENUM and companion ToString array. Try to follow this convention through out and it will become natural.

写下不归期 2024-11-22 05:21:56

这类似于按像素发布的“X”宏。
的链接

感谢您提供 http://en.wikipedia.org/wiki/X_Macro中生成的代码 宏可能很棘手且难以调试。
相反,生成一个由“正常”代码使用的表。
我发现很多人反对让宏生成代码,
这可能是采用“X Macros”技术的原因之一
在 wiki 中并未被广泛采用。

通过生成表格,您仍然只需要编辑一处即可扩展列表,
由于您无法在调试器中“单步执行”表,因此这会删除
许多人反对将多行代码隐藏在宏中。

//------------------------------------------------------------------------------
// enum to string example
#define FOR_EACH_GENDER(tbd) \
        tbd(GENDER_MALE) \
        tbd(GENDER_FEMALE) \
        tbd(GENDER_INTERSEX) \

#define ONE_GENDER_ENUM(name) name,
enum
{
    FOR_EACH_GENDER(ONE_GENDER_ENUM)
    MAX_GENDER
};

#define ONE_GENDER(name) #name,
static const char *enumGENDER_TO_STRING[] = 
{
    FOR_EACH_GENDER(ONE_GENDER)
};

// access string name with enumGENDER_TO_STRING[value]
// or, to be safe converting from a untrustworthy caller
static const char *enumGenderToString(unsigned int value)
{
    if (value < MAX_GENDER)
    {
        return enumGENDER_TO_STRING[value];
    }
    return NULL;
}

static void printAllGenders(void)
{
    for (int ii = 0;  ii < MAX_GENDER;  ii++)
    {
        printf("%d) gender %s\n", ii, enumGENDER_TO_STRING[ii]);
    }
}

//------------------------------------------------------------------------------
// you can assign an arbitrary value and/or information to each enum,
#define FOR_EACH_PERSON(tbd) \
        tbd(2, PERSON_FRED,     "Fred",     "Weasley", GENDER_MALE,   12) \
        tbd(4, PERSON_GEORGE,   "George",   "Weasley", GENDER_MALE,   12) \
        tbd(6, PERSON_HARRY,    "Harry",    "Potter",  GENDER_MALE,   10) \
        tbd(8, PERSON_HERMIONE, "Hermione", "Granger", GENDER_FEMALE, 10) \

#define ONE_PERSON_ENUM(value, ename, first, last, gender, age) ename = value,
enum
{
    FOR_EACH_PERSON(ONE_PERSON_ENUM)
};

typedef struct PersonInfoRec
{
    int value;
    const char *ename;
    const char *first;
    const char *last;
    int gender;
    int age;
} PersonInfo;

#define ONE_PERSON_INFO(value, ename, first, last, gender, age) \
                     { ename, #ename, first, last, gender, age },
static const PersonInfo personInfo[] = 
{
    FOR_EACH_PERSON(ONE_PERSON_INFO)
    { 0, NULL, NULL, NULL, 0, 0 }
};
// note: if the enum values are not sequential, you need another way to lookup
// the information besides personInfo[ENUM_NAME]

static void printAllPersons(void)
{
    for (int ii = 0;  ;  ii++)
    {
        const PersonInfo *pPI = &personInfo[ii];
        if (!pPI->ename)
        {
            break;
        }
        printf("%d) enum %-15s  %8s %-8s %13s %2d\n",
            pPI->value, pPI->ename, pPI->first, pPI->last,
            enumGenderToString(pPI->gender), pPI->age);
    }
}

This is similar to the "X" macro post by pixel.
thanks for the link to http://en.wikipedia.org/wiki/X_Macro

Code generated in macros can be tricky and hard to debug.
Instead, generate a table that is used by "normal" code.
I find that many people object to having macros generate code,
and may be one reason the technique of "X Macros" as presented
in the wiki is not widely adopted.

By generating a table, you still need only edit one place to extend the list,
and since you can't "step through" a table in the debugger, this removes the
objection from many people about multi-lines of code buried in macros.

//------------------------------------------------------------------------------
// enum to string example
#define FOR_EACH_GENDER(tbd) \
        tbd(GENDER_MALE) \
        tbd(GENDER_FEMALE) \
        tbd(GENDER_INTERSEX) \

#define ONE_GENDER_ENUM(name) name,
enum
{
    FOR_EACH_GENDER(ONE_GENDER_ENUM)
    MAX_GENDER
};

#define ONE_GENDER(name) #name,
static const char *enumGENDER_TO_STRING[] = 
{
    FOR_EACH_GENDER(ONE_GENDER)
};

// access string name with enumGENDER_TO_STRING[value]
// or, to be safe converting from a untrustworthy caller
static const char *enumGenderToString(unsigned int value)
{
    if (value < MAX_GENDER)
    {
        return enumGENDER_TO_STRING[value];
    }
    return NULL;
}

static void printAllGenders(void)
{
    for (int ii = 0;  ii < MAX_GENDER;  ii++)
    {
        printf("%d) gender %s\n", ii, enumGENDER_TO_STRING[ii]);
    }
}

//------------------------------------------------------------------------------
// you can assign an arbitrary value and/or information to each enum,
#define FOR_EACH_PERSON(tbd) \
        tbd(2, PERSON_FRED,     "Fred",     "Weasley", GENDER_MALE,   12) \
        tbd(4, PERSON_GEORGE,   "George",   "Weasley", GENDER_MALE,   12) \
        tbd(6, PERSON_HARRY,    "Harry",    "Potter",  GENDER_MALE,   10) \
        tbd(8, PERSON_HERMIONE, "Hermione", "Granger", GENDER_FEMALE, 10) \

#define ONE_PERSON_ENUM(value, ename, first, last, gender, age) ename = value,
enum
{
    FOR_EACH_PERSON(ONE_PERSON_ENUM)
};

typedef struct PersonInfoRec
{
    int value;
    const char *ename;
    const char *first;
    const char *last;
    int gender;
    int age;
} PersonInfo;

#define ONE_PERSON_INFO(value, ename, first, last, gender, age) \
                     { ename, #ename, first, last, gender, age },
static const PersonInfo personInfo[] = 
{
    FOR_EACH_PERSON(ONE_PERSON_INFO)
    { 0, NULL, NULL, NULL, 0, 0 }
};
// note: if the enum values are not sequential, you need another way to lookup
// the information besides personInfo[ENUM_NAME]

static void printAllPersons(void)
{
    for (int ii = 0;  ;  ii++)
    {
        const PersonInfo *pPI = &personInfo[ii];
        if (!pPI->ename)
        {
            break;
        }
        printf("%d) enum %-15s  %8s %-8s %13s %2d\n",
            pPI->value, pPI->ename, pPI->first, pPI->last,
            enumGenderToString(pPI->gender), pPI->age);
    }
}
多情出卖 2024-11-22 05:21:56
  1. 宏:

    #define stringWithLiteral(literal) @#literal
    
  2. 枚举:

    typedef NS_ENUM(NSInteger, EnumType) {
        枚举类型0,
        枚举类型1,
        枚举类型2
    };
    
  3. 数组:

    static NSString * const EnumTypeNames[] = {
        stringWithLiteral(EnumType0),
        stringWithLiteral(EnumType1),
        stringWithLiteral(EnumType2)
    };
    
  4. 使用:

    EnumType enumType = ...;
    NSString *enumName = EnumTypeNames[enumType];
    

==== 编辑 ====

将以下代码复制到您的项目并运行。

#define stringWithLiteral(literal) @#literal

typedef NS_ENUM(NSInteger, EnumType) {
    EnumType0,
    EnumType1,
    EnumType2
};

static NSString * const EnumTypeNames[] = {
    stringWithLiteral(EnumType0),
    stringWithLiteral(EnumType1),
    stringWithLiteral(EnumType2)
};

- (void)test {
    EnumType enumType = EnumType1;
    NSString *enumName = EnumTypeNames[enumType];
    NSLog(@"enumName: %@", enumName);
}
  1. a macro:

    #define stringWithLiteral(literal) @#literal
    
  2. an enum:

    typedef NS_ENUM(NSInteger, EnumType) {
        EnumType0,
        EnumType1,
        EnumType2
    };
    
  3. an array:

    static NSString * const EnumTypeNames[] = {
        stringWithLiteral(EnumType0),
        stringWithLiteral(EnumType1),
        stringWithLiteral(EnumType2)
    };
    
  4. using:

    EnumType enumType = ...;
    NSString *enumName = EnumTypeNames[enumType];
    

==== EDIT ====

Copy the following code to your project and run.

#define stringWithLiteral(literal) @#literal

typedef NS_ENUM(NSInteger, EnumType) {
    EnumType0,
    EnumType1,
    EnumType2
};

static NSString * const EnumTypeNames[] = {
    stringWithLiteral(EnumType0),
    stringWithLiteral(EnumType1),
    stringWithLiteral(EnumType2)
};

- (void)test {
    EnumType enumType = EnumType1;
    NSString *enumName = EnumTypeNames[enumType];
    NSLog(@"enumName: %@", enumName);
}
彡翼 2024-11-22 05:21:56

这是工作代码
https://github.com/ndpiparava/ObjcEnumString

//1st Approach
#define enumString(arg) (@""#arg)

//2nd Approach

+(NSString *)secondApproach_convertEnumToString:(StudentProgressReport)status {

    char *str = calloc(sizeof(kgood)+1, sizeof(char));
    int  goodsASInteger = NSSwapInt((unsigned int)kgood);
    memcpy(str, (const void*)&goodsASInteger, sizeof(goodsASInteger));
    NSLog(@"%s", str);
    NSString *enumString = [NSString stringWithUTF8String:str];
    free(str);

    return enumString;
}

//Third Approcah to enum to string
NSString *const kNitin = @"Nitin";
NSString *const kSara = @"Sara";


typedef NS_ENUM(NSUInteger, Name) {
    NameNitin,
    NameSara,
};

+ (NSString *)thirdApproach_convertEnumToString :(Name)weekday {

    __strong NSString **pointer = (NSString **)&kNitin;
    pointer +=weekday;
    return *pointer;
}

Here is working code
https://github.com/ndpiparava/ObjcEnumString

//1st Approach
#define enumString(arg) (@""#arg)

//2nd Approach

+(NSString *)secondApproach_convertEnumToString:(StudentProgressReport)status {

    char *str = calloc(sizeof(kgood)+1, sizeof(char));
    int  goodsASInteger = NSSwapInt((unsigned int)kgood);
    memcpy(str, (const void*)&goodsASInteger, sizeof(goodsASInteger));
    NSLog(@"%s", str);
    NSString *enumString = [NSString stringWithUTF8String:str];
    free(str);

    return enumString;
}

//Third Approcah to enum to string
NSString *const kNitin = @"Nitin";
NSString *const kSara = @"Sara";


typedef NS_ENUM(NSUInteger, Name) {
    NameNitin,
    NameSara,
};

+ (NSString *)thirdApproach_convertEnumToString :(Name)weekday {

    __strong NSString **pointer = (NSString **)&kNitin;
    pointer +=weekday;
    return *pointer;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文