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 el mensaje [self toString:JSON]
fue enviado; 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, me sale un error. ¿Qué me estoy perdiendo?
c
objective-c
enums
typedef
craig
fuente
fuente
Respuestas:
Esta es realmente una pregunta C, no específica de Objective-C (que es un superconjunto del lenguaje C). Las enumeraciones en C se representan como enteros. Por lo tanto, debe escribir una función que devuelva una cadena dada un valor de enumeración. Hay muchas maneras de hacer esto. Una matriz de cadenas de modo que el valor enum se pueda usar como un índice en la matriz o una estructura de mapa (por ejemplo, an
NSDictionary
) que mapea un valor enum a un trabajo de cadena, pero encuentro que estos enfoques no son tan claros como una función que hace que la conversión sea explícita (y el enfoque de matriz, aunque laC
forma clásica es peligrosa si los valores de su enumeración no son distintos de 0). Algo como esto funcionaría:Su pregunta relacionada sobre la sintaxis correcta para un valor de enumeración es que usa solo el valor (por ejemplo
JSON
), no laFormatType.JSON
sintaxis.FormatType
es un tipo y los valores de enumeración (pJSON
. ej .XML
, etc.) son valores que puede asignar a ese tipo.fuente
No puedes hacerlo fácilmente. En C y Objective-C, las enumeraciones son realmente constantes enteras glorificadas. Tendrá que generar una tabla de nombres usted mismo (o con algún abuso de preprocesador). Por ejemplo:
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 algunos abusos del preprocesador, pero es complicado y feo.
También tenga en cuenta que esto supone que tiene una constante enum válida. Si usted tiene un valor entero de una fuente no confiable, que, además, tenga que hacer una verificación de que su constante es válido, por ejemplo, mediante la inclusión de un valor "pasado max" en su enumeración, o comprobando si es menor que la longitud de la matriz,
sizeof(FormatType_toString) / sizeof(FormatType_toString[0])
.fuente
string[] = { [XML] = "XML" }
para asegurarse de que la cadena coincida con las enumeraciones correctamenteFormatType_toString[]
matriz y llamar-isEqualToString:
a cada elemento para encontrar una coincidencia, o usar un tipo de datos de mapeo comoNSDictionary
para mantener el mapa de búsqueda inversa.FormatType_toString
matriz.Mi solución:
editar: He agregado una solución aún mejor al final, usando Modern Obj-C
1.
Ponga los nombres como claves en una matriz.
Asegúrese de que los índices son las enumeraciones apropiadas y en el orden correcto (de lo contrario, excepción).
nota: nombres es una propiedad sintetizada como * _nombres *;
no se verificó la compilación del código, pero utilicé la misma técnica en mi aplicación.
//
2.
Usando Modern Obj-C puedes usar un diccionario para vincular las descripciones a las claves en la enumeración.
El orden NO importa .
Uso (en un método de instancia de clase):
fuente
+[typeDisplayNames]
, está recreando el diccionario. Esto está bien si solo se llama unas pocas veces, pero si se llama muchas veces, esto será muy costoso. Una mejor solución puede ser convertir el diccionario en un singleton, por lo que solo se crea una vez y, de lo contrario, permanece en la memoria. Memoria clásica frente al enigma de la CPU.static NSDictionary *dict = nil; if(!dict) dict = @{@(UserTypeParent): @"Parent"}; return dict;
comentarios no le permitirán un salto de línea, lo siento.Combinando la respuesta de @AdamRosenfield, el comentario de @Christoph y otro truco para manejar enumeraciones en C simples, sugiero:
En el peor de los casos, como si cambia la enumeración pero olvida cambiar la matriz de nombres, devolverá nil para esta clave.
fuente
define typedef enum en el encabezado de clase:
escribe un método como este en clase:
tener las cadenas dentro del archivo Localizable.strings :
fuente
Usaría el token de cadena # del compilador (junto con las macros para hacerlo todo más compacto):
fuente
Me gusta la
#define
forma de hacer esto:// Coloque esto en su archivo .h, fuera del bloque @interface
fuente(fuente ya no está disponible)fuente
nil
siarray.count <= enumValue
?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 de enumeración 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 hágase la pregunta antes de usar esto, ¿estoy en lo cierto, de hecho, 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 Initials", todos usan esto o su nombre, parece):
MyWonderfulType.h
:Y
MyWonderfulType.m
:fuente
Otra solución:
En su método puede usar:
fuente
Respuesta mejorada @ yar1vn al eliminar la dependencia de la cadena:
Por lo tanto, cuando cambie el nombre de la entrada enum, se cambiará la cadena correspondiente. Útil en caso de que no vaya a mostrar esta cadena al usuario.
fuente
"foo""bar"
, se genera la cadena"foobar"
cuando se compila. Entonces,#define VariableName(arg) (@""#arg)
se expandiráVariableName(MyEnum)
para ser(@"""MyEnum")
. Eso dará como resultado la cadena@"MyEnum"
.Dada una definición de enumeración como:
Podemos definir una macro para convertir un valor de enumeración en su cadena correspondiente, como se muestra a continuación.
La
switch
declaración utilizada en el bloque es para la verificación de tipos y también para obtener el soporte de autocompletar en Xcode.fuente
Tenía un tipo enumerado grande que quería convertirlo en una
NSDictionary
búsqueda. Terminé usandosed
desde el terminal OSX como:que se puede leer como: 'captura la primera palabra en la línea y genera @ (palabra): @ "palabra",'
Esta expresión regular convierte la enumeración en un archivo de encabezado llamado 'ObservationType.h' que contiene:
en algo como:
que luego se puede envolver en un método que usa la sintaxis moderna del objetivo-c
@{ }
(como se explica en @ yar1vn arriba) para crear unaNSDictionary
búsqueda:La
dispatch_once
placa de la caldera es solo para garantizar que la variable estática se inicialice de manera segura.Nota: Encontré que la expresión regex de sed en OSX es extraña; cuando traté de usar
+
para hacer coincidir 'uno o más', no funcionó y tuve que recurrir a usarla{1,}
como reemplazofuente
Utilizo una variación en la respuesta de Barry Walk, que en orden de importancia:
P.EJ:
fuente
@pixel agregó la respuesta más brillante aquí: https://stackoverflow.com/a/24255387/1364257 ¡ Por favor, vótelo!
Utiliza la ordenada macro X de la década de 1960. (He cambiado un poco su código para el ObjC moderno)
Eso es. Limpio y aseado. Gracias a @pixel! https://stackoverflow.com/users/21804/pixel
fuente
Combiné varios enfoques aquí. Me gusta la idea del preprocesador y la lista indexada.
No hay asignación dinámica adicional, y debido a la alineación, el compilador podría optimizar la búsqueda.
fuente
En primer lugar, con respecto a FormatType.JSON: JSON no es miembro de FormatType, es un posible valor 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 mapeo. 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", para que así sea,
NSString *FormatTypeJSON = @"JSON"
y así sucesivamente.fuente
Lo siguiente proporciona una solución tal que agregar una nueva enumeración requiere solo una edición de una línea, un trabajo similar a agregar una sola línea en una lista de enumeración {}.
fuente
Cada respuesta aquí básicamente dice lo mismo, crea una enumeración regular y luego usa un captador personalizado para cambiar entre cadenas.
Utilizo una solución mucho más simple que es más rápida, más corta y más limpia, ¡usando Macros!
¡Entonces simplemente puede comenzar a escribir
kNam...
y autocompletar mostrará las listas que desee!Además, si desea manejar la lógica de todos los nombres a la vez, simplemente puede enumerar rápidamente la matriz literal en orden, de la siguiente manera:
for (NSString *kName in kNames_allNames) {}
Por último, la conversión de NSString en las macros garantiza un comportamiento similar al de typedef!
¡Disfrutar!
fuente
Muchas respuestas, todas bastante buenas.
Si buscas una solución genérica de Objective C que usa 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 que se parezca más al conjunto de funciones NSStringFromXXX que prevalecen en las API de Apple.
Necesitará
#import "NSStringFromEnum.h"
encontrarlo aquí http://pastebin.com/u83RR3Vk[EDITAR] también necesita
#import "SW+Variadic.h"
encontrarse aquí http://pastebin.com/UEqTzYLfEjemplo 1: defina completamente un NUEVO enum typedef, con convertidores de cadenas.
en mi archivo.h
en myfile.m:
usar :
NSStringFromEnumDispatch_chain_cmd(chain_for_c)
devoluciones@"chain_for_c"
enumDispatch_chain_cmdFromNSString(@"chain_previous")
devolucioneschain_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 el cambio de nombre del nombre de tipo utilizado en las funciones.
en mi archivo.h
en myfile.m:
fuente
Aquí está trabajando -> https://github.com/ndpiparava/ObjcEnumString
fuente
Dependiendo de sus necesidades, podría utilizar alternativamente las directivas del compilador para simular el comportamiento que está buscando.
Solo recuerde las deficiencias habituales del compilador (no escribir con seguridad, copiar y pegar directamente aumenta el tamaño del archivo fuente)
fuente
#define
esté visible, no podrá usar el valor de enumeración real (es decir,JSON
será reemplazado@"JSON"
por el preprocesador y generará un error de compilación al asignar a unFormatType
.)