枚举值为NSString(iOS)

我有一个枚举持有几个值:

enum {value1,value2,value3} myValue;

在我的应用程序的某个点上,我想检查枚举的哪个值现在处于活动状态。 我正在使用NSLog,但我不清楚如何显示枚举的当前值(值1 /值2 /值3 / etc …)作为NSLog的NSString。

任何人?

这里回答了一些关于实施的build议

底线是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; } 

我不喜欢把枚举放在堆上,没有提供翻译的堆函数。 以下是我想到的:

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

这将保持枚举和string声明紧密结合在一起,以便在需要时进行更新。

现在,在代码的任何地方,你可以像这样使用枚举/macros:

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

为了保证元素索引,你总是可以显式声明开始(或全部)枚举值。

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

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

我想用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; 

创build一个方法如下:

 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. 命名你的function。

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

  3. 放一些@“和逗号

  4. 利润!!!!

这将由编译器validation,所以你不会意外混淆索引。

 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] 

我发现这个网站 (从下面的例子是采取),这个问题提供了一个优雅的解决scheme。 原来的post虽然来自这个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; } 

如果我可以提供另一种解决scheme,它具有types检查的附加好处,如果您在转换中缺lessenum值,可读性和简洁性,则会发出警告。

对于你给定的例子: 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 } 

有了这个你得到了types安全( NSInteger在这种情况下),你设置预期的枚举偏移量( = 0 )。

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

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

然后就像任何其他NSString一样使用“named”string来操作:

 @interface MyData : NSObject @property (copy, nonatomic) ImageType imageType; @end @implementation MyData - (void)doSomething { //... self.imageType = ImageTypePng; //... if ([self.imageType isEqualToString:ImageTypeJpg]) { //... } } @end 

下面的解决scheme使用预处理器的string操作符,允许更优雅的解决scheme。 它可以让你在一个地方定义枚举术语,以提高抵制错误的能力。

首先,以下面的方式定义你的枚举。

 #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 

@像素的答案指出我在正确的方向。

你可以使用Xmacros – 它们是完美的。

好处 1.实际枚举值和string值之间的关系是在一个地方。 2.你可以在你的代码中使用常规的switch语句。

损害 1.初始设置代码有一点钝,并使用有趣的macros。

代码

 #define X(a, b, c) ab, 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; } 

从二十世纪六十年代开始,这种模式已经出现了(不要开玩笑!): http : //en.wikipedia.org/wiki/X_Macro

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

我希望你们都能find有用的东西,因为我发现有这么多其他的StackOverflow解决scheme是有用的。

 - (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]); 

请享用! 😉

下面是一个Enum Struct的例子,如果您需要在Objective-C中编写的遗留项目中使用Swift Code,那么它就是Objective-C友好的。

例:

contentType.filename。 的toString()

返回“文件名”


contentType.filename。 rawValue

返回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 

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

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

这与像素的“X”macros相似。 感谢您的链接http://en.wikipedia.org/wiki/X_Macro

在macros中生成的代码可能非常棘手,难以debugging。 相反,生成一个由“普通”代码使用的表。 我发现很多人反对使用macros来生成代码,这可能是维基中提供的“Xmacros”技术没有被广泛采用的原因之一。

通过生成一个表格,你仍然只需要编辑一个地方来扩展列表,而且由于不能在debugging器中“遍历”一个表格,这就消除了许多人对于embedded在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); } } 
  1. 一个macros:

     #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]; 

====编辑====

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

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

这里是工作代码 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; }