枚举值为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]; }
你所要做的就是:
-
命名你的function。
-
复制NSArray * arr = @ [和]之间的枚举和粘贴内容; return(NSString *)[arr objectAtIndex:input];
-
放一些@“和逗号
-
利润!!!!
这将由编译器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); } }
-
一个macros:
#define stringWithLiteral(literal) @#literal
-
枚举:
typedef NS_ENUM(NSInteger, EnumType) { EnumType0, EnumType1, EnumType2 };
-
数组:
static NSString * const EnumTypeNames[] = { stringWithLiteral(EnumType0), stringWithLiteral(EnumType1), stringWithLiteral(EnumType2) };
-
使用:
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; }