with switch protocol parameter generic enum ios enums nsstring

ios - switch - swift4 enum



enum Valores para NSString(iOS) (15)

Tengo una enumeración que tiene varios valores:

enum {value1, value2, value3} myValue;

En cierto punto de mi aplicación, deseo verificar qué valor de la enumeración está ahora activo. Estoy usando NSLog, pero no tengo claro cómo mostrar el valor actual de la enumeración (value1 / valu2 / valu3 / etc ...) como NSString para NSLog.

¿Nadie?


  1. una macro:

    #define stringWithLiteral(literal) @#literal

  2. una enumeración:

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

  3. una matriz:

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

  4. utilizando:

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

==== EDITAR ====

Copie el siguiente código en su proyecto y ejecútelo.

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


A continuación se muestra un ejemplo de Enum Struct que es amigable para Objective-C en caso de que necesite usar Swift Code en proyectos Legacy escritos en Objective-C.

Ejemplo:

contentType.filename. Encadenar()

devuelve "nombre de archivo"

contentType.filename. valor bruto

devuelve el valor Int, 1 (ya que es el segundo elemento en 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


Aquí hay una solución plug-and-play que puede ampliar con una simple copia y pegue de sus definiciones EXISTENTES.

Espero que todos ustedes lo encuentren útil, ya que he encontrado útiles muchas otras soluciones de .

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

Aquí están las declaraciones de ejemplo:

typedef enum _type1 { ExampleNonExplicitTypeNEItemName1, ExampleNonExplicitTypeNEItemName2, ExampleNonExplicitTypeNEItemName3 } ExampleNonExplicitType; typedef enum _type2 { ExampleExplicitAssignsTypeEAItemName1 = 1, ExampleExplicitAssignsTypeEAItemName2 = 2, ExampleExplicitAssignsTypeEAItemName3 = 4 } ExampleExplicitAssignsType;

Aquí hay una llamada de ejemplo:

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

¡Disfrutar! ;-)


En algunos casos, cuando necesita convertir enum -> NSString y NSString -> enumerar, podría ser más simple usar un typedef y #define (o const NSStrings) en lugar de enum:

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

y luego solo opere con cadenas "con nombre" como con cualquier otra cadena NSS:

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


Encontré este website (del cual se toma el siguiente ejemplo) que proporciona una solución elegante a este problema. Sin embargo, la publicación original proviene de esta respuesta de .

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


Esta es una vieja pregunta, pero si tienes una enumeración no contigua utiliza un literal de diccionario en lugar de una matriz:

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


Esto es similar a la macro "publicación" por píxel. gracias por el enlace a http://en.wikipedia.org/wiki/X_Macro

El código generado en macros puede ser complicado y difícil de depurar. En su lugar, genere una tabla que sea usada por el código "normal". Encuentro que muchas personas se oponen a que las macros generen código, y puede ser una de las razones por las que la técnica de "X Macros" tal como se presenta en el wiki no es ampliamente adoptada.

Al generar una tabla, solo necesita editar un lugar para extender la lista, y como no puede "atravesar" una tabla en el depurador, esto elimina la objeción de muchas personas acerca de las líneas múltiples de código oculto en las 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); } }


Esto se responde aquí: algunas sugerencias sobre la implementación

La línea de fondo es Objective-C está usando una C enum normal, antigua, que es solo un conjunto glorificado de enteros.

Dada una enum como esta:

typedef enum { a, b, c } FirstThreeAlpha;

Su método se vería así:

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


Esto será validado por el compilador, por lo que no confundirá los índices accidentalmente.

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]


La siguiente solución utiliza el operador de cordaje del preprocesador, lo que permite una solución más elegante. Te permite definir los términos enum en un solo lugar para una mayor resistencia contra los errores tipográficos.

Primero, defina su enumeración de la siguiente manera.

#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

Ahora, úsalo de la siguiente manera:

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

qué salidas:

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

La respuesta de @ pixel me indicó la dirección correcta.


No me gusta poner la enumeración en el montón, sin proporcionar una función de montón para la traducción. Esto es lo que se me ocurrió:

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

Esto mantiene las declaraciones de cadena y enum juntas para facilitar la actualización cuando sea necesario.

Ahora, en cualquier parte del código, puede usar la enumeración / macro de esta manera:

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

Para garantizar los índices de los elementos, siempre puede declarar explícitamente los valores enum de inicio (o todos).

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


Podría usar macros X, son perfectos para esto.

Beneficios 1. la relación entre el valor real de la enumeración y el valor de la cadena está en un lugar. 2. puede usar declaraciones de cambio regulares más adelante en su código.

Detrimento 1. El código de configuración inicial es un poco obtuso y utiliza macros divertidas.

El código

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

Ahora puedes hacer:

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

Este patrón ha existido desde los años 60 (¡no es broma!): http://en.wikipedia.org/wiki/X_Macro


Presentaré es la forma en que uso, y se ve mejor que la respuesta anterior. (Creo)

Me gustaría ilustrar con UIImageOrientation para una fácil comprensión.

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;

crea un método como:

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

Todo lo que tienes que hacer es :

  1. nombra tu función.

  2. copie el contenido de enum y pegue eso entre NSArray * arr = @ [ and ]; return (NSString *) [arr objectAtIndex: entrada];

  3. poner algunos @, ", y coma

  4. ¡¡¡¡LUCRO!!!!


Si puedo ofrecer otra solución que tenga el beneficio adicional de verificar el tipo, advierta si le falta un valor enum en su conversión, legibilidad y brevedad.

Para su ejemplo dado: typedef enum { value1, value2, value3 } myValue; Puedes hacerlo:

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

Como nota al margen. Es un mejor enfoque para declarar tus enumeraciones así:

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

Con esto obtienes seguridad de tipo ( NSInteger en este caso), estableces el offset enum esperado ( = 0 ).


Aquí está el código de trabajo 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; }