uso tipos programaciĆ³n definidos c objective-c enums typedef

tipos - typedef struct en c



Convierta object-c typedef a su cadena equivalente (20)

@pixel agregó la respuesta más brillante aquí: https://stackoverflow.com/a/24255387/1364257 Por favor, votale!

Él usa la ordenada macro X de la década de 1960. (He cambiado su código un poco para el ObjC moderno)

#define X(a, b, c) a b, enum ZZObjectType { XXOBJECTTYPE_TABLE }; typedef NSUInteger TPObjectType; #undef X #define XXOBJECTTYPE_TABLE / X(ZZObjectTypeZero, = 0, @"ZZObjectTypeZero") / X(ZZObjectTypeOne, , @"ZZObjectTypeOne") / X(ZZObjectTypeTwo, , @"ZZObjectTypeTwo") / X(ZZObjectTypeThree, , @"ZZObjectTypeThree") + (NSString*)nameForObjectType:(ZZObjectType)objectType { #define X(a, b, c) @(a):c, NSDictionary *dict = @{XXOBJECTTYPE_TABLE}; #undef X return dict[objectType]; }

Eso es. Limpio y aseado. ¡Gracias a @pixel! https://stackoverflow.com/users/21804/pixel

Suponiendo que tengo un typedef declarado en mi archivo .h como tal:

typedef enum { JSON, XML, Atom, RSS } FormatType;

Me gustaría construir una función que convierta el valor numérico de typedef en una cadena. Por ejemplo, si se envió el mensaje [self toString:JSON] ; devolvería ''JSON''.

La función se vería así:

-(NSString *) toString:(FormatType)formatType { //need help here return []; }

Por cierto, si intento esta sintaxis

[self toString:FormatType.JSON];

para pasar el valor typedef al método, obtengo un error. ¿Qué me estoy perdiendo?


A continuación, se proporciona una solución para que agregar una nueva enumeración requiera solo una edición de una línea, un trabajo similar a agregar una sola línea en una lista enum {}.

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


Aquí está trabajando -> 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; }


Combiné varios enfoques aquí. Me gusta la idea del preprocesador y la lista indexada.

No hay una asignación dinámica adicional, y debido a la inclusión, el compilador podría optimizar la búsqueda.

typedef NS_ENUM(NSUInteger, FormatType) { FormatTypeJSON = 0, FormatTypeXML, FormatTypeAtom, FormatTypeRSS, FormatTypeCount }; NS_INLINE NSString *FormatTypeToString(FormatType t) { if (t >= FormatTypeCount) return nil; #define FormatTypeMapping(value) [value] = @#value NSString *table[FormatTypeCount] = {FormatTypeMapping(FormatTypeJSON), FormatTypeMapping(FormatTypeXML), FormatTypeMapping(FormatTypeAtom), FormatTypeMapping(FormatTypeRSS)}; #undef FormatTypeMapping return table[t]; }


Combinando la respuesta de @AdamRosenfield, el comentario de @Christoph y otro truco para manejar los enunciados simples, sugiero:

// In a header file typedef enum { JSON = 0, // explicitly indicate starting index XML, Atom, RSS, FormatTypeCount, // keep track of the enum size automatically } FormatType; extern NSString *const FormatTypeName[FormatTypeCount]; // In a source file NSString *const FormatTypeName[FormatTypeCount] = { [JSON] = @"JSON", [XML] = @"XML", [Atom] = @"Atom", [RSS] = @"RSS", }; // Usage NSLog(@"%@", FormatTypeName[XML]);

En el peor de los casos, como si cambiaras la enumeración pero te olvides de cambiar la matriz de nombres, devolverá nil para esta clave.


Dada una definición enum como:

typedef NS_ENUM(NSInteger, AssetIdentifier) { Isabella, William, Olivia };

Podemos definir una macro para convertir un valor enum a su cadena correspondiente, como se muestra a continuación.

#define AssetIdentifier(asset) / ^(AssetIdentifier identifier) { / switch (identifier) { / case asset: / default: / return @#asset; / } / }(asset)

La instrucción de switch utilizada en el bloque es para verificación de tipos, y también para obtener el soporte de autocompletar en Xcode.


Dependiendo de sus necesidades, podría usar alternativamente directivas de compilación para simular el comportamiento que está buscando.

#define JSON @"JSON" #define XML @"XML" #define Atom @"Atom" #define RSS @"RSS"

Solo recuerda las deficiencias habituales del compilador (no escribe seguro, copia y pega directamente hace que el archivo fuente sea más grande)


En primer lugar, con respecto a FormatType.JSON: JSON no es miembro de FormatType, es un valor posible del tipo. FormatType ni siquiera es un tipo compuesto; es un escalar.

En segundo lugar, la única forma de hacerlo es crear una tabla de asignación. La forma más común de hacer esto en Objective-C es crear una serie de constantes que se refieran a sus "símbolos", por lo que tendría NSString *FormatTypeJSON = @"JSON" y así sucesivamente.


Esta es realmente una pregunta C, no específica de Objective-C (que es un superconjunto del lenguaje C). Los mensajes en C se representan como números enteros. Por lo tanto, debe escribir una función que devuelva una cadena con un valor enum. Hay muchas maneras de hacer esto. Una matriz de cadenas tal que el valor enum se puede usar como un índice en la matriz o una estructura de mapa (por ejemplo, un NSDictionary ) que mapea un valor enum para un trabajo de cadena, pero encuentro que estos enfoques no son tan claros como una función eso hace explícita la conversión (y el enfoque de matriz, aunque la forma clásica de C es peligrosa si sus valores enum no son contiguos desde 0). Algo como esto funcionaría:

- (NSString*)formatTypeToString:(FormatType)formatType { NSString *result = nil; switch(formatType) { case JSON: result = @"JSON"; break; case XML: result = @"XML"; break; case Atom: result = @"Atom"; break; case RSS: result = @"RSS"; break; default: [NSException raise:NSGenericException format:@"Unexpected FormatType."]; } return result; }

Su pregunta relacionada sobre la sintaxis correcta para un valor de enum es que usa solo el valor (por ejemplo, JSON ), no el FormatType.JSON formato FormatType.JSON sytax. FormatType es un tipo y los valores enum (por ejemplo, JSON , XML , etc.) son valores que puede asignar a ese tipo.


Hice una especie de combinación de todas las soluciones encontradas en esta página para crear la mía, es una especie de extensión enum orientada a objetos o algo así.

De hecho, si necesita algo más que constantes (es decir, enteros), probablemente necesite un objeto modelo (todos estamos hablando de MVC, ¿verdad?)

Simplemente pregúntese la pregunta antes de usar esto, ¿estoy en lo cierto, realmente no necesita un objeto modelo real, inicializado desde un servicio web, un plist, una base de datos SQLite o CoreData?

De todos modos aquí viene el código (MPI es para "My Project Iniciales", todo el mundo usa esto o su nombre, parece):

MyWonderfulType.h :

typedef NS_ENUM(NSUInteger, MPIMyWonderfulType) { MPIMyWonderfulTypeOne = 1, MPIMyWonderfulTypeTwo = 2, MPIMyWonderfulTypeGreen = 3, MPIMyWonderfulTypeYellow = 4, MPIMyWonderfulTypePumpkin = 5 }; #import <Foundation/Foundation.h> @interface MyWonderfulType : NSObject + (NSString *)displayNameForWonderfulType:(MPIMyWonderfulType)wonderfulType; + (NSString *)urlForWonderfulType:(MPIMyWonderfulType)wonderfulType; @end

Y MyWonderfulType.m :

#import "MyWonderfulType.h" @implementation MyWonderfulType + (NSDictionary *)myWonderfulTypeTitles { return @{ @(MPIMyWonderfulTypeOne) : @"One", @(MPIMyWonderfulTypeTwo) : @"Two", @(MPIMyWonderfulTypeGreen) : @"Green", @(MPIMyWonderfulTypeYellow) : @"Yellow", @(MPIMyWonderfulTypePumpkin) : @"Pumpkin" }; } + (NSDictionary *)myWonderfulTypeURLs { return @{ @(MPIMyWonderfulTypeOne) : @"http://www.theone.com", @(MPIMyWonderfulTypeTwo) : @"http://www.thetwo.com", @(MPIMyWonderfulTypeGreen) : @"http://www.thegreen.com", @(MPIMyWonderfulTypeYellow) : @"http://www.theyellow.com", @(MPIMyWonderfulTypePumpkin) : @"http://www.thepumpkin.com" }; } + (NSString *)displayNameForWonderfulType:(MPIMyWonderfulType)wonderfulType { return [MPIMyWonderfulType myWonderfulTypeTitles][@(wonderfulType)]; } + (NSString *)urlForWonderfulType:(MPIMyWonderfulType)wonderfulType { return [MPIMyWonderfulType myWonderfulTypeURLs][@(wonderfulType)]; } @end


Me gusta la forma #define de hacer esto:

// Coloque esto en su archivo .h, fuera del bloque @interface

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

source (fuente no disponible)


Mi solución:

editar: agregué incluso una mejor solución al final, usando Modern Obj-C

1.
Pon nombres como claves en una matriz.
Asegúrese de que los índices sean las enumeraciones apropiadas y en el orden correcto (de lo contrario, excepción).
nota: nombres es una propiedad sintetizada como * _names *;

el código no fue verificado para compilación, pero utilicé la misma técnica en mi aplicación.

typedef enum { JSON, XML, Atom, RSS } FormatType; + (NSArray *)names { static NSMutableArray * _names = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _names = [NSMutableArray arrayWithCapacity:4]; [_names insertObject:@"JSON" atIndex:JSON]; [_names insertObject:@"XML" atIndex:XML]; [_names insertObject:@"Atom" atIndex:Atom]; [_names insertObject:@"RSS" atIndex:RSS]; }); return _names; } + (NSString *)nameForType:(FormatType)type { return [[self names] objectAtIndex:type]; }


//

2.
Usando Modern Obj-C usted puede usar un diccionario para unir descripciones a las claves en la enumeración.
El orden NO importa

typedef NS_ENUM(NSUInteger, UserType) { UserTypeParent = 0, UserTypeStudent = 1, UserTypeTutor = 2, UserTypeUnknown = NSUIntegerMax }; @property (nonatomic) UserType type; + (NSDictionary *)typeDisplayNames { return @{@(UserTypeParent) : @"Parent", @(UserTypeStudent) : @"Student", @(UserTypeTutor) : @"Tutor", @(UserTypeUnknown) : @"Unknown"}; } - (NSString *)typeDisplayName { return [[self class] typeDisplayNames][@(self.type)]; }


Uso (en un método de instancia de clase):

NSLog(@"%@", [self typeDisplayName]);



Muchas respuestas son bastante buenas.

Si busca una solución genérica de Objective C que use algunas macros ...

La característica clave es que utiliza la enumeración como un índice en una matriz estática de constantes NSString. la matriz en sí está envuelta en una función para hacerla más parecida al conjunto de funciones NSStringFromXXX que prevalecen en las API de Apple.

necesitarás #import "NSStringFromEnum.h" aquí http://pastebin.com/u83RR3Vk

[EDIT] también necesita #import "SW+Variadic.h" encuentra aquí http://pastebin.com/UEqTzYLf

Ejemplo 1: defina completamente un nuevo typedef enum, con convertidores de cadenas.

en myfile.h

#import "NSStringFromEnum.h" #define define_Dispatch_chain_cmd(enum)/ enum(chain_done,=0)/ enum(chain_entry)/ enum(chain_bg)/ enum(chain_mt)/ enum(chain_alt)/ enum(chain_for_c)/ enum(chain_while)/ enum(chain_continue_for)/ enum(chain_continue_while)/ enum(chain_break_for)/ enum(chain_break_while)/ enum(chain_previous)/ enum(chain_if)/ enum(chain_else)/ interface_NSString_Enum_DefinitionAndConverters(Dispatch_chain_cmd)

en myfile.m:

#import "myfile.h" implementation_NSString_Enum_Converters(Dispatch_chain_cmd)

usar :

NSString *NSStringFromEnumDispatch_chain_cmd(enum Dispatch_chain_cmd value);

NSStringFromEnumDispatch_chain_cmd(chain_for_c) returns @"chain_for_c"

enum Dispatch_chain_cmd enumDispatch_chain_cmdFromNSString(NSString *value);

enumDispatch_chain_cmdFromNSString(@"chain_previous") devuelve chain_previous

Ejemplo 2: proporcionar rutinas de conversión para una enumeración existente también demuestra el uso de una cadena de configuración y cambiar el nombre de tipo utilizado en las funciones.

en myfile.h

#import "NSStringFromEnum.h" #define CAEdgeAntialiasingMask_SETTINGS_PARAMS CAEdgeAntialiasingMask,mask,EdgeMask,edgeMask interface_NSString_Enum_Converters(CAEdgeAntialiasingMask_SETTINGS_PARAMS)

en myfile.m:

// we can put this in the .m file as we are not defining a typedef, just the strings. #define define_CAEdgeAntialiasingMask(enum)/ enum(kCALayerLeftEdge)/ enum(kCALayerRightEdge)/ enum(kCALayerBottomEdge)/ enum(kCALayerTopEdge) implementation_NSString_Enum_Converters(CAEdgeAntialiasingMask_SETTINGS_PARAMS)


No puedes hacerlo fácilmente. En C y Objective-C, las enumeraciones son realmente solo constantes enteras glorificadas. Tendrá que generar una tabla de nombres usted mismo (o con algún abuso de preprocesador). Por ejemplo:

// In a header file typedef enum FormatType { JSON, XML, Atom, RSS } FormatType; extern NSString * const FormatType_toString[]; // In a source file // initialize arrays with explicit indices to make sure // the string match the enums properly NSString * const FormatType_toString[] = { [JSON] = @"JSON", [XML] = @"XML", [Atom] = @"Atom", [RSS] = @"RSS" }; ... // To convert enum to string: NSString *str = FormatType_toString[theEnumValue];

El peligro de este enfoque es que si alguna vez cambia la enumeración, debe recordar cambiar la matriz de nombres. Puede resolver este problema con un poco de abuso de preprocesador, pero es complicado y feo.

También tenga en cuenta que esto supone que tiene una constante de enumeración válida. Si tiene un valor entero de una fuente que no es de confianza, también necesita verificar que su constante sea válida, por ejemplo, incluyendo un valor "pasado máximo" en su enumeración, o verificando si es menor que la longitud de la matriz, sizeof(FormatType_toString) / sizeof(FormatType_toString[0]) .


Otra solución:

typedef enum BollettinoMavRavTypes { AMZCartServiceOperationCreate, AMZCartServiceOperationAdd, AMZCartServiceOperationGet, AMZCartServiceOperationModify } AMZCartServiceOperation; #define AMZCartServiceOperationValue(operation) [[[NSArray alloc] initWithObjects: @"CartCreate", @"CartAdd", @"CartGet", @"CartModify", nil] objectAtIndex: operation];

En tu método puedes usar:

NSString *operationCheck = AMZCartServiceOperationValue(operation);


Respuesta @ yar1vn mejorada al descartar la dependencia de cadenas:

#define VariableName(arg) (@""#arg) typedef NS_ENUM(NSUInteger, UserType) { UserTypeParent = 0, UserTypeStudent = 1, UserTypeTutor = 2, UserTypeUnknown = NSUIntegerMax }; @property (nonatomic) UserType type; + (NSDictionary *)typeDisplayNames { return @{@(UserTypeParent) : VariableName(UserTypeParent), @(UserTypeStudent) : VariableName(UserTypeStudent), @(UserTypeTutor) : VariableName(UserTypeTutor), @(UserTypeUnknown) : VariableName(UserTypeUnknown)}; } - (NSString *)typeDisplayName { return [[self class] typeDisplayNames][@(self.type)]; }

Por lo tanto, cuando cambie el nombre de la entrada enum, se cambiará la cadena correspondiente. Útil en caso de que no le muestres esta cadena al usuario.


Tenía un tipo enumerado grande que quería convertir en una búsqueda NSDictionary . Terminé usando sed de la terminal OSX como:

$ sed -E ''s/^[[:space:]]{1,}([[:alnum:]]{1,}).*$/ @(/1) : @"/1",/g'' ObservationType.h

que se puede leer como: ''captura la primera palabra en la línea y muestra @ (palabra): @'' palabra '',''

Esta expresión regular convierte la enumeración en un archivo de encabezado denominado ''ObservationType.h'' que contiene:

typedef enum : int { ObservationTypePulse = 1, ObservationTypeRespRate = 2, ObservationTypeTemperature = 3, . . }

en algo así como:

@(ObservationTypePulse) : @"ObservationTypePulse", @(ObservationTypeRespRate) : @"ObservationTypeRespRate", @(ObservationTypeTemperature) : @"ObservationTypeTemperature", . .

que luego puede ser envuelto en un método usando la sintaxis objetiva-c moderna @{ } (como se explica por @ yar1vn arriba) para crear una búsqueda NSDictionary :

-(NSDictionary *)observationDictionary { static NSDictionary *observationDictionary; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ observationDictionary = [[NSDictionary alloc] initWithDictionary:@{ @(ObservationTypePulse) : @"ObservationTypePulse", @(ObservationTypeRespRate) : @"ObservationTypeRespRate", . . }]; }); return observationDictionary; }

La placa de la caldera dispatch_once es solo para garantizar que la variable estática se inicialice de una manera segura para la ejecución de subprocesos.

Nota: Encontré la expresión sedgegege en OSX impar - cuando traté de usar + para que coincida con "uno o más" no funcionó y tuve que recurrir al uso de {1,} como reemplazo


Usaría el token de # cadena del compilador (junto con las macros para hacerlo todo más compacto):

#define ENUM_START / NSString* ret; / switch(value) { #define ENUM_CASE(evalue) / case evalue: / ret = @#evalue; / break; #define ENUM_END / } / return ret; NSString* _CvtCBCentralManagerStateToString(CBCentralManagerState value) { ENUM_START ENUM_CASE(CBCentralManagerStateUnknown) ENUM_CASE(CBCentralManagerStateResetting) ENUM_CASE(CBCentralManagerStateUnsupported) ENUM_CASE(CBCentralManagerStateUnauthorized) ENUM_CASE(CBCentralManagerStatePoweredOff) ENUM_CASE(CBCentralManagerStatePoweredOn) ENUM_END }


Utilizo una variación en la respuesta de Barry Walk, que en orden de importancia:

  1. Permite al compilador verificar las cláusulas de caso faltantes (no puede si tiene una cláusula predeterminada).
  2. Utiliza un nombre típico de Objective-C (en lugar de un nombre similar a Java).
  3. Plantea una excepción específica
  4. Es mas corto

P.EJ:

- (NSString*)describeFormatType:(FormatType)formatType { switch(formatType) { case JSON: return @"JSON"; case XML: return @"XML"; case Atom: return @"Atom"; case RSS: return @"RSS"; } [NSException raise:NSInvalidArgumentException format:@"The given format type number, %ld, is not known.", formatType]; return nil; // Keep the compiler happy - does not understand above line never returns! }


define typedef enum en el encabezado de la clase:

typedef enum { IngredientType_text = 0, IngredientType_audio = 1, IngredientType_video = 2, IngredientType_image = 3 } IngredientType;

escribe un método como este en clase:

+ (NSString*)typeStringForType:(IngredientType)_type { NSString *key = [NSString stringWithFormat:@"IngredientType_%i", _type]; return NSLocalizedString(key, nil); }

tener las cadenas dentro del archivo Localizable.strings :

/* IngredientType_text */ "IngredientType_0" = "Text"; /* IngredientType_audio */ "IngredientType_1" = "Audio"; /* IngredientType_video */ "IngredientType_2" = "Video"; /* IngredientType_image */ "IngredientType_3" = "Image";