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

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

Me gustaría construir una función que convierte el valor numérico de la typedef a una cadena. Por ejemplo, si el mensaje [self toString:JSON] fue enviado; volvería ‘JSON’.

La función sería algo como esto:

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

Por cierto, si me trate de esta sintaxis

[self toString:FormatType.JSON];

para pasar el typedef valor para el método, me sale un error. Lo que me estoy perdiendo?

InformationsquelleAutor craig | 2009-07-07

21 Comentarios

  1. 132

    Esto es realmente un C pregunta, no específico para Objective-C (que es un superconjunto del lenguaje C). Las enumeraciones en C se representan como números enteros. Por lo que necesita para escribir una función que devuelve un string dado un valor de enumeración. Hay muchas maneras de hacer esto. Una matriz de cadenas que el valor de enumeración puede ser utilizado como un índice en el array o un mapa de la estructura (por ejemplo, un NSDictionary) que se asigna un valor de enumeración para una cadena de trabajo, pero me parece que estos métodos no son tan claras como una función que hace que la conversión explícita (y la matriz de planteamiento, aunque el clásico C camino es peligroso si su enumeración de los valores de continguous desde 0). Algo como esto:

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

    Tu relacionados con la pregunta acerca de la sintaxis correcta para un valor de enumeración es la que se utiliza sólo el valor (por ejemplo,JSON), no la FormatType.JSON sytax. FormatType es un tipo y los valores de enumeración (por ejemplo,JSON, XML, etc.) son valores que se pueden asignar a ese tipo.

  2. 125

    Usted no puede hacerlo fácilmente. En C y Objective-C, las enumeraciones son realmente glorificado constantes enteras. Usted tendrá que generar una tabla de nombres de sí mismo (o con algún preprocesador de abuso). 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 cambio de la enumeración, usted tiene que recordar para cambiar la matriz de nombres. Este problema se puede solucionar con algunos de preprocesador abuso, pero es complicado y feo.

    También tenga en cuenta que esto supone una enumeración válido constante. Si usted tiene un valor entero de una fuente no confiable, que además, tendrá que hacer una verificación de que la constante es válido, por ejemplo, mediante la inclusión de un «pasado» max » valor en su enumeración, o mediante la comprobación de si es menor que la longitud de matriz, sizeof(FormatType_toString) /sizeof(FormatType_toString[0]).

    • se pueden inicializar las matrices con el consentimiento explícito de los índices, por ejemplo, la string[] = { [XML] = "XML" } para asegurarse de que la cadena coincide con el de las enumeraciones correctamente
    • Sí, esa es una C99 característica llamada designados inicializadores. Eso está bien para usar en Objective-C (que se basa en C99), pero para los genéricos C89 código, usted no puede usar esas.
    • Hay alguna forma de ir a otro lado? Por ejemplo, la enumeración de vuelta dada una cadena de caracteres?
    • Sí, pero no es tan simple como hacer una matriz de búsqueda. Ya sea que usted necesita para iterar a través de la FormatType_toString[] de la matriz y de la llamada -isEqualToString: en cada elemento para encontrar una coincidencia, o el uso de una asignación de tipo de datos, tales como NSDictionary para mantener la inversa de la búsqueda de mapa.
    • El truco de Max O que es bueno acerca de olvidar añadir entradas en el FormatType_toString matriz.
    • interruptor sería la mejor manera de superar el peligro de la actualización de la matriz con respecto a la enumeración.
    • typedef enum FormatType : NSString debe ser cambiado a typedef enum FormatType : NSUInteger. Me pregunto nadie se dio cuenta de que. En segundo lugar, pasar de una enumeración no válido FormatType_toString[5] de accidente
    • Fijo que ahora, gracias por la captura de ese. Ese error se introdujo por otro usuario que editó esta respuesta hace un tiempo, y nadie lo cogió hasta ahora.
    • la adición de comprobaciones cada vez que la matriz de nosotros accede parece ser factible que el uso de los diccionarios con el valor de la clave par?

  3. 49

    Mi solución:

    edit: he añadido una solución mejor al final, el uso de las Modernas Obj-C

    1.
    Poner los nombres como las claves de una matriz.

    Asegúrese de que los índices son los adecuados enumeraciones, y en el orden correcto (de lo contrario excepción).

    nota: nombres es una propiedad que se sintetiza como *_names*;

    código no fue marcado para la compilación, pero he utilizado la misma técnica que 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.
    El uso de las Modernas Obj-C, podemos utilizar un diccionario para atar las descripciones de las claves de la enumeración.
    NO importa el orden.

    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 una clase de método de instancia):

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

    • Tenga en cuenta que, cada vez que usted llame +[typeDisplayNames], tienes que volver a crear el diccionario. Esto está bien si solo es llamado un par de veces, pero si es llamado muchas veces, este será un proceso muy caro. Una mejor solución puede ser hacer que el diccionario de singleton, por lo que sólo se crea una vez y se queda en la memoria de otra manera. Clásico de la memoria vs CPU enigma.
    • O cambiarlo para que sea una variable estática, por ejemplo, static NSDictionary *dict = nil; if(!dict) dict = @{@(UserTypeParent): @"Parent"}; return dict; Comentarios no permiten el salto de línea, lo siento por eso.
  4. 28

    La combinación de @AdamRosenfield respuesta, @Christoph comentario y otro truco para manejar llanura C enumeraciones 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 el cambio de la enumeración, pero se olvidan de cambiar los nombres de matriz devolverá nil para esta clave.

  5. 12

    definir typedef enum en el encabezado de la clase:

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

    escribir un método como este en clase:

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

    tienen las cadenas dentro de Localizable.las cadenas de de archivo:

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

    Me gustaría utilizar el compilador # token de cadena (junto con macros para hacer 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
    }
    • Esto funcionó muy bien en C99 – soy nuevo en C, y he encontrado esto para ser la forma más limpia para lograr la pregunta. También he añadido en un defecto en mi aplicación para los elementos que no han sido definidos. Muy limpio método. Gracias por los resultados. Muy astuto uso de una Macro.
  7. 8

    Me gusta el #define forma de hacer esto:

    //Lugar esta en su .h archivo, fuera de la @bloque de interfaz

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

    fuente (fuente ya no está disponible)

    • demasiado frágil y demasiado fatal si se llama con un valor incorrecto
    • lo que trata de devolver nil si array.count <= enumValue?
    • que la captura de los errores .. sería alféizar de ser frágil porque si agrega un valor de enumeración O el valor entero de un valor de enumeración de los cambios que esto va mal. El aceptó la respuesta sería bueno
    • enlace no encontrado ;-(
    • lo siento – no estoy seguro de lo que le pasó a ese sitio web. No en el Camino de Vuelta Cuando la máquina…
    • Tengo una pequeña pregunta en la respuesta anterior. Cómo convertir el elemento de cadena para kImageType. Necesito llamar a la imageTypeEnumToString método por el paso de la cadena.Puede usted por favor me ayude a salir de mi problema.
    • Me gusta esta respuesta mejor, porque usted tiene la cadena de definiciones de la derecha al lado de las enumeraciones. Menos probabilidad de perder valor. Y @Ganesh, para convertir de raw valor, podría hacer esto: retorno (kImageType)[imageTypeArray indexOfObject:rawValue];
    • Peligroso, pero hizo lo que yo necesitaba en el barato. Hábilmente rodea en #si la depuración de los cheques, que nunca deberían ver la luz de producción y sólo aquellos castigados serán los responsables.

  8. 8

    Me hizo una especie de mezcla de todas las soluciones que se encuentran en esta página para crear el mío, es un tipo de objeto orientado a la enumeración de extensión o
    algo.

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

    Sólo pregúntate a ti mismo antes de usar este, estoy en lo cierto, o no, de hecho, la necesidad de un verdadero modelo de objeto inicializado desde un webservice, un plist, una base de datos SQLite o CoreData ?

    De todos modos aquí viene el código (MPI es para «Mi Proyecto Iniciales», todo el mundo usa 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
    • se ve bien, pero se están asignando y regresar completos diccionarios cuando sólo se necesita uno de sus valores. Eficiencia VS Bastante código? depende de lo que usted quiere y usted va a estar bien con esto si no los uso tanto en el código como en un gran bucle. Pero esta será tal vez útil con «dinámico» o no-rígida de las enumeraciones que viene de un servidor, por ejemplo
  9. 5

    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 su método que puede utilizar:

    NSString *operationCheck = AMZCartServiceOperationValue(operation);
  10. 4

    Mejorado @yar1vn respuesta al quitar la cadena de la dependencia:

    #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 usted va a cambiar enum nombre de la entrada correspondiente de la cadena ser cambiado.
    Útil en caso de que si usted no va a mostrar esta cadena de usuario.

    • Puede usted explicar «– definir VariableName(arg) (@»»#arg) — y, probablemente, dar una mejor solución ?
    • Con #define, cuando se utiliza # para una sustitución, el argumento se ajusta automáticamente en comillas dobles. En C, cuando dos cadenas aparecen uno al lado del otro en el código como "foo""bar", que se traduce en la cadena de "foobar" cuando se compila. Así, #define VariableName(arg) (@""#arg) ampliará VariableName(MyEnum) a ser (@"""MyEnum"). Que se traducirá en la cadena de @"MyEnum".
  11. 2

    Yo tenía un gran tipo enumerado que quería convertir en un NSDictionary de búsqueda. Terminé usando sed de OSX terminal como:

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

    que se puede leer como: «captura de la primera palabra en la línea de salida y @(palabra) : @»palabra»,’

    Esta expresión se convierte la enumeración en un archivo de encabezado denominado ‘ObservationType.h’ que contiene:

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

    algo como:

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

    que luego puede ser envuelto en un método que utiliza la moderna objective-c sintaxis @{ } (según lo explicado por @yar1vn arriba) para crear un NSDictionary búsqueda :

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

    La dispatch_once de la caldera de la placa es sólo para asegurarse de que la variable estática es inicializado en un hilo de un modo seguro.

    Nota: he encontrado la sed expresión regex en OSX impar – cuando traté de usar + para que coincida con «uno o más» no funcionó y tuvo que recurrir a la utilización de {1,} como un reemplazo

  12. 2

    Yo uso una variación en Barry Pie de la respuesta, que en orden de importancia:

    1. Permite al compilador para comprobar si faltan caso de las cláusulas (no se si tiene una cláusula por defecto).
    2. Utiliza un Objetivo-C nombre típico (en lugar de Java como nombre).
    3. Plantea una excepción específica.
    4. Es más corto.

    Por ejemplo:

    - (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!
    }
  13. 2

    @pixel añadido la más brillante respuesta aquí:
    https://stackoverflow.com/a/24255387/1364257
    Por favor, upvote él!

    Él utiliza la ordenada X macro a partir de la década de 1960. (He cambiado su código un poco de la moderna ObjC)

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

    Que es. Limpio y ordenado.
    Gracias a @pixel! https://stackoverflow.com/users/21804/pixel

    • Gracias por la respuesta, pero tenemos una definición diferente de limpiar..
    • proporcionar su solución, hombre. Es fácil a la carpa a alguien. Esta solución tiene sus obvias ventajas y obvio los contras de ambos. Hacer un mundo mejor con su solución.
  14. 2

    Dado una definición enum como:

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

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

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

    La switch declaración utilizado en el bloque para la comprobación de tipos, y también para obtener el auto-apoyo en Xcode.

    Convertir objective-c typedef para su cadena equivalente
    Convertir objective-c typedef para su cadena equivalente

  15. 2

    He combinado varios enfoques.
    Me gusta la idea de que el preprocesador y el indexado de la lista.

    Hay ninguna asignación dinámica, y debido a las alineaciones que el compilador podría ser capaz de 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];
    }
  16. 1

    Primera de todas, con respecto a FormatType.JSON: JSON no es un miembro de FormatType, es un valor posible de la tipo. FormatType no es ni siquiera un tipo compuesto — es un escalar.

    Segundo, la única manera de hacer esto es crear una tabla de asignación. La manera más común de hacer esto en Objective-C es crear una serie de constantes en referencia a su «símbolos», de manera que tendría NSString *FormatTypeJSON = @"JSON" y así sucesivamente.

  17. 1

    la siguiente proporciona una solución tal que para agregar un nuevo enum requiere
    sólo una línea de edición, un trabajo similar a la adición de una sola línea en un enum {} lista.

    //------------------------------------------------------------------------------
    //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);
    }
    }
    • Esta técnica se llama X-Macro, en caso de que alguien quiere leer sobre él. Que viene del hecho de que, tradicionalmente, la FOR_EACH_GENDER() macro fue siempre llamado X(). Una cosa que usted puede querer hacer es #undef FOR_EACH_GENDER antes de definirla con un nuevo significado.
  18. 1

    Cada respuesta aquí básicamente dice lo mismo, crear una regular enum y, a continuación, usar un getter para cambiar entre las cadenas.

    Puedo contratar a una solución mucho más sencilla que es más rápido, más corto y más limpio—uso de los Macros!


    #define kNames_allNames ((NSArray <NSString *> *)@[@"Alice", @"Bob", @"Eve"])
    #define kNames_alice ((NSString *)kNames_allNames[0])
    #define kNames_bob ((NSString *)kNames_allNames[1])
    #define kNames_eve ((NSString *)kNames_allNames[2])

    Entonces usted puede simplemente comenzar a escribir kNam... y autocompletar mostrará las listas que deseo!

    Además, si usted desea para manejar la lógica de todos los nombres a la vez usted puede simplemente rápido enumerar los literales de matriz en orden, de la siguiente manera:

    for (NSString *kName in kNames_allNames) {}

    Por último, el NSString de fundición en las macros asegura un comportamiento similar al typedef!


    Disfrutar!

  19. 0

    Muchas respuestas, todas muy buenas.

    Si usted está después de un genérico, Objective C solución que utiliza algunas macros…

    Característica clave es que utiliza la enumeración como un índice en una matriz estática de NSString constantes.
    la propia matriz está envuelto en una función para que sea más como la suite de NSStringFromXXX funciones prevalentes en la Api de Apple.

    deberá #import "NSStringFromEnum.h" encontrar aquí
    http://pastebin.com/u83RR3Vk

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

    Ejemplo 1 : definir completamente un NUEVO typedef enum, con cadena de convertidores.

    en miarchivo.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 miarchivo.m:


     #import "myfile.h"
    implementation_NSString_Enum_Converters(Dispatch_chain_cmd)

    a utilizar :

    NSString *NSStringFromEnumDispatch_chain_cmd(enum Dispatch_chain_cmd value);

    NSStringFromEnumDispatch_chain_cmd(chain_for_c) devuelve @"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 un enum existentes
    también se muestra el uso de una configuración de cadena, y el cambio de nombre de la nombre utilizado en las funciones.

    en miarchivo.h


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

    en miarchivo.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)
  20. 0

    Aquí hay 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;
    }
  21. -2

    Dependiendo de sus necesidades, usted puede de forma alternativa el uso de directivas de compilador para simular el comportamiento que usted está buscando.

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

    Sólo recuerda la costumbre compilador deficiencias, (no tipo de seguro, directo copy-paste es la fuente de archivo más grande)

    • No creo que este va a trabajar; en cualquier lugar de la #define es visible, usted no será capaz de utilizar el real valor de enumeración (es decir, JSON serán reemplazados con @"JSON" por el preprocesador y resultará en un error de compilador a la hora de asignar a un FormatType.

Dejar respuesta

Please enter your comment!
Please enter your name here