枚举值到NSString(iOS)

时间:2011-06-13 14:27:19

标签: ios enums nsstring

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

枚举{value1,value2,value3} myValue;

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

任何?

16 个答案:

答案 0 :(得分:83)

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

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};

答案 1 :(得分:55)

在此处回答:a few suggestions on implementation

底线是Objective-C正在使用常规的旧C enum,这只是一组美化的整数。

鉴于此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;
}

答案 2 :(得分:34)

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

我想用 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. PROFIT !!!!

答案 3 :(得分:29)

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

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

var stateStrings: [MCSessionState: String] = [
    MCSessionState.NotConnected : "MCSessionState.NotConnected",
    MCSessionState.Connecting : "MCSessionState.Connecting",
    MCSessionState.Connected : "MCSessionState.Connected"
]
var stateString = stateStrings[MCSessionState.Connected]

答案 4 :(得分:13)

我发现这个website(从下面的例子中可以看出),它为这个问题提供了一个优雅的解决方案。原始帖子来自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;
}

答案 5 :(得分:6)

如果我可以提供另一种具有类型检查功能的附加解决方案,如果您在转换,可读性和简洁性方面缺少枚举值,则会发出警告。

对于您的示例: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)。

答案 6 :(得分:5)

在某些情况下,当您需要转换枚举时 - &gt; NSString和NSString - &gt;枚举使用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

答案 7 :(得分:4)

下面的解决方案使用预处理器的stringize运算符,从而提供更优雅的解决方案。它允许您在一个位置定义枚举术语,以便更好地抵御拼写错误。

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

#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的回答指出了我正确的方向。

答案 8 :(得分:2)

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

我希望你们都觉得它很有用,因为我发现有很多其他的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]);

享受! ; - )

答案 9 :(得分:2)

你可以使用X宏 - 它们非常适合这种情况。

<强>优势  1.实际枚举值和字符串值之间的关系在一个地方。  2.您可以稍后在代码中使用常规切换语句。

<强>损害  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

答案 10 :(得分:2)

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

示例:

contentType.filename。 toString()

  

返回&#34;文件名&#34;

contentType.filename。 rawValue

  

返回Int Value,1 (因为它是struct上的第二项)

-(NSInteger)getNumberOfLinesInLabelOrTextView:(id)obj
{
    NSInteger lineCount = 0;
    if([obj isKindOfClass:[UILabel class]])
    {
        UILabel *label = (UILabel *)obj;
        CGSize requiredSize = [label.text boundingRectWithSize:CGSizeMake(CGRectGetWidth(label.frame), CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:label.font} context:nil].size;

        int charSize = label.font.leading;
        // now listen , you need to set the text or label with only 1 
        // then nslog(@"%d",charSize);
        // then change the line int charSize = label.font.leading; into 
        // int charSize = the printed value in case of 1 line
        int rHeight = requiredSize.height;

        lineCount = rHeight/charSize;
    }
    else if ([obj isKindOfClass:[UITextView class]])
    {
        UITextView *textView = (UITextView *)obj;
        lineCount = textView.contentSize.height / textView.font.leading;
    }

    return lineCount;
}

答案 11 :(得分:2)

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

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 ) ] \
)

答案 12 :(得分:1)

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

将此添加到.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"
};

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

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

因此,此模式取决于公认的NS_ENUM命名约定和配套的ToString数组。尝试完全遵循这个约定,它将变得很自然。

答案 13 :(得分:0)

这类似于&#34; X&#34;宏按照像素。 感谢http://en.wikipedia.org/wiki/X_Macro

的链接

在宏中生成的代码可能很棘手且难以调试。 相反,生成一个由&#34; normal&#34;使用的表。码。 我发现许多人反对让宏生成代码, 并且可能是&#34; X Macros&#34;技术的一个原因。如上所述 在wiki中没有被广泛采用。

通过生成表格,您仍然只需要编辑一个地点来扩展列表, 因为你不能逐步完成&#34;调试器中的表,这将删除 许多人反对埋藏在宏中的多行代码。

//------------------------------------------------------------------------------
// 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);
    }
}

答案 14 :(得分:0)

  1. 一个宏:

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

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

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

    EnumType enumType = ...;
    NSString *enumName = EnumTypeNames[enumType];
    
  5. ====编辑====

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

    #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);
    }
    

答案 15 :(得分:0)

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;
}