Перечислим значения в NSString (iOS) - PullRequest
63 голосов
/ 13 июня 2011

У меня есть перечисление, содержащее несколько значений:

enum {value1, value2, value3} myValue;

В определенный момент в моем приложении я хочупроверьте, какое значение перечисления сейчас активно.Я использую NSLog, но мне не ясно, как отобразить текущее значение перечисления (value1 / valu2 / valu3 / etc ...) в качестве строки NSSt для NSLog.

Anyone?

Ответы [ 16 ]

2 голосов
/ 17 июня 2014

Вы можете использовать макросы X - они идеально подходят для этого.

Преимущества 1. связь между фактическим значением перечисления и значением строки находится в одном месте. 2. Вы можете использовать регулярные операторы switch позже в своем коде.

* 1008 Ущерб * 1. Код начальной настройки немного тупой и использует забавные макросы.

Код

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

Теперь вы можете сделать:

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

Эта модель существует с 1960-х годов (без шуток!): http://en.wikipedia.org/wiki/X_Macro

2 голосов
/ 25 июля 2013

Вот решение plug-and-play, которое вы можете расширить, просто скопировав и вставив свои СУЩЕСТВУЮЩИЕ определения.

Я надеюсь, что вы все найдете это полезным, так как я нашел полезными многие другие решения StackOverflow.

- (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]);

Наслаждайтесь! ; -)

1 голос
/ 24 октября 2018

Предположим, требуется перечислить список языков.

Добавить это в файл .h

typedef NS_ENUM(NSInteger, AvailableLanguage) {
  ENGLISH,
  GERMAN,
  CHINENSE
};

Теперь в файле .m просто создайте массив, например,

// Try to use the same naming convention throughout. 
// That is, adding ToString after NS_ENUM name;

NSString* const AvailableLanguageToString[] = {
  [ENGLISH] = @"English",
  [GERMAN]  = @"German",
  [CHINESE] = @"Chinese"
};

Вот и все.Теперь вы можете использовать enum с легким и получить строку для перечислений, используя массив.Например,

- (void) setPreferredLanguage:(AvailableLanguage)language {
  // this will get the NSString* for the language.
  self.preferredLanguage = AvailableLanguageToString[language];
}

Таким образом, этот шаблон зависит от принятого соглашения об именах NS_ENUM и сопутствующего массива ToString.Попробуйте следовать этому соглашению, и оно станет естественным.

0 голосов
/ 05 марта 2017

Вот рабочий код 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;
}
0 голосов
/ 19 августа 2016
  1. макрос:

    #define stringWithLiteral(literal) @#literal
    
  2. перечисление:

    typedef NS_ENUM(NSInteger, EnumType) {
        EnumType0,
        EnumType1,
        EnumType2
    };
    
  3. массив:

    static NSString * const EnumTypeNames[] = {
        stringWithLiteral(EnumType0),
        stringWithLiteral(EnumType1),
        stringWithLiteral(EnumType2)
    };
    
  4. с помощью:

    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);
}
0 голосов
/ 21 декабря 2014

Это похоже на пост макроса "X" по пикселям.спасибо за ссылку на http://en.wikipedia.org/wiki/X_Macro

Код, сгенерированный в макросах, может быть сложным и сложным для отладки.Вместо этого создайте таблицу, которая используется «нормальным» кодом.Я нахожу, что многие люди возражают против того, чтобы макросы генерировали код, и это может быть одной из причин, по которой методика «X-макросов», представленная в вики, не получила широкого распространения.одно место для расширения списка, и так как вы не можете «пройтись» по таблице в отладчике, это снимает у многих возражения по поводу многострочного кода, скрытого в макросах.

//------------------------------------------------------------------------------
// 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);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...