将Objective-C Typedef转换为其等效字符串


141

假设我在.h文件中声明了typedef,如下所示:

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

我想构建一个将typedef的数值转换为字符串的函数。例如,如果消息[self toString:JSON]已发送;它将返回“ JSON”。

该函数将如下所示:

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

顺便说一句,如果我尝试这种语法

[self toString:FormatType.JSON];

将typedef值传递给方法,我得到一个错误。我想念什么?


请参阅我在stackoverflow.com/questions/6331762/enum-values-to-nsstring-ios上的答案,以获取更清洁的解决方案。
BooTooMany 2014年

4
也许我们应该在枚举时拥抱Swift语言。
Itachi

@craig:这是解决方案 github.com/ndpiparava/ObjcEnumString
Nitin

对于不简单使用用于转换为字符串的枚举的自定义获取方法的解决方案,请查看字符串广播宏数组:stackoverflow.com/a/53755377/2057171
Albert Renshaw

Answers:


135

这实际上是一个C问题,并非特定于Objective-C(它是C语言的超集)。C中的枚举表示为整数。因此,您需要编写一个返回给定枚举值的字符串的函数。有很多方法可以做到这一点。字符串数组,使得枚举值可用作数组或NSDictionary将枚举值映射到字符串作品的映射结构(例如)的索引,但是我发现这些方法不如函数使转换显式(以及数组方法,尽管经典C方法很危险,如果枚举值从0开始不是连续的)。这样的事情会起作用:

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

有关枚举值的正确语法的相关问题是,您仅使用值(例如JSON),而不使用FormatType.JSON语法。FormatType是一种类型,而枚举值(例如JSONXML等)是可以分配给该类型的值。


127

你不能轻易做到。在C和Objective-C中,枚举实际上只是美化的整数常量。您必须自己生成一个名称表(或使用一些预处理程序)。例如:

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

这种方法的危险在于,如果您更改了枚举,则必须记住要更改名称数组。您可以使用一些预处理器滥用来解决此问题,但这既棘手又难看。

另请注意,这假设您具有有效的枚举常量。如果您有来自不受信任来源的整数值,则还需要检查您的常数是否有效,例如,通过在枚举中包含“过去最大”值,或者检查其是否小于数组长度,sizeof(FormatType_toString) / sizeof(FormatType_toString[0])


37
您可以使用显式索引初始化数组,例如string[] = { [XML] = "XML" },确保字符串正确匹配枚举
Christoph

@Christoph:是的,这是称为指定的初始化程序的C99功能。可以在Objective-C(基于C99)中使用它,但是对于通用C89代码,您不能使用它们。
亚当·罗森菲尔德

还有其他方法吗?例如,返回给定的字符串枚举?
Jameo 2014年

1
@Jameo:是的,但是它不像执行数组查找那样简单。您将需要遍历FormatType_toString[]数组并调用-isEqualToString:每个元素以找到匹配项,或者使用映射数据类型NSDictionary来维护逆向查找图。
亚当·罗森菲尔德2014年

1
Max O的窍门在于忘记在FormatType_toString数组中添加条目。
AechoLiu 2015年

50

我的解决方案:

编辑:最后,我使用Modern Obj-C

1 添加了更好的解决方案
将名称作为键放入数组中。
确保索引是适当的枚举,并且顺序正确(否则例外)。
注意:名字是综合为* _names *的属性;

未检查代码进行编译,但我在应用程序中使用了相同的技术。

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.
使用Modern Obj-C,您可以使用字典将描述与枚举中的键相关联。
订购无所谓

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


用法(在类实例方法中):

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



12
请注意,每次调用时+[typeDisplayNames],您都在重新创建字典。如果只调用几次,这很好,但是如果调用多次,这将变得非常昂贵。更好的解决方案可能是使字典成为单例,因此仅创建一次字典,否则保留在内存中。经典内存与CPU难题。
Joel Fischer 2014年

或者将其更改为静态变量,例如,static NSDictionary *dict = nil; if(!dict) dict = @{@(UserTypeParent): @"Parent"}; return dict;注释不会让您换行,对此表示抱歉。
natanavra

29

我建议结合@AdamRosenfield答案,@ Christoph注释和另一个处理普通C枚举的技巧:

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

在最坏的情况下(例如,如果您更改枚举但忘记更改名称数组),它将为此键返回nil。


12

在类头中定义typedef枚举:

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

在类中编写这样的方法:

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

Localizable.strings文件中包含字符串:

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

11

我将使用编译器的#字符串令牌(以及宏,使其更加紧凑):

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

这在C99中非常有效-我是C的新手,我发现这是解决所提问题的最干净的方法。我还为实现中的未定义项添加了默认值。很干净的方法。感谢您的结果。非常巧用Macro。
TravisWhidden '16

8

我喜欢#define这样做的方式:

//将其放置在@interface块之外的.h文件中

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

来源(来源不再可用)


@ Daij-Djan nil如果返回array.count <= enumValue怎么办?
anneblue 2014年

@anneblue会捕获错误..这将是脆弱的,因为如果您添加枚举值或枚举值的整数值更改,则会出错。公认的答案会很好
Daij-Djan

@codercat :(对不起-不确定该网站发生了什么事。当机器出现
故障

我对上述答案有一个小问题。如何将字符串元素转换为kImageType。我需要通过传递字符串来调用imageTypeEnumToString方法。您能帮我解决我的问题吗?
Ganesh,2014年

1
我最喜欢这个答案,因为您在枚举旁边有字符串定义。缺少值的机会很小。从原始值转换为@Ganesh可以做到这一点:return(kImageType)[imageTypeArray indexOfObject:rawValue];
哈里斯

8

我混合了在此页面上找到的所有解决方案来创建我的解决方案,这是一种面向对象的枚举扩展。

实际上,如果您不仅需要常量(即整数),还可能需要模型对象(我们都在谈论MVC,对吗?)

在使用此功能之前,只问自己一个问题,对吗,实际上,您是否需要一个真正的模型对象,该对象是通过Web服务,plist,SQLite数据库或CoreData初始化的?

无论如何,这里都有代码(MPI用于“我的项目缩写”,似乎每个人都使用它或他们的名字):

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

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

看起来不错,但是当您只需要其值之一时就可以分配和返回完整的字典。效率VS漂亮代码?取决于您想要的内容,如果您不像在一个巨大的循环中那样在代码中使用它们太多,就可以了。但这可能对例如来自服务器的“动态”或非硬编码枚举很有用
user2387149

5

另一个解决方案:

typedef enum BollettinoMavRavTypes {
    AMZCartServiceOperationCreate,
    AMZCartServiceOperationAdd,
    AMZCartServiceOperationGet,
    AMZCartServiceOperationModify
} AMZCartServiceOperation;

#define AMZCartServiceOperationValue(operation) [[[NSArray alloc] initWithObjects: @"CartCreate", @"CartAdd", @"CartGet", @"CartModify", nil] objectAtIndex: operation];

在您的方法中,您可以使用:

NSString *operationCheck = AMZCartServiceOperationValue(operation);

4

通过删除字符串依赖项改进了@ yar1vn答案:

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

因此,当您更改枚举条目名称时,相应的字符串将被更改。如果您不打算向用户显示此字符串,则很有用。


您能解释一下“-定义VariableName(arg)(@”“#arg)---并可能给出更好的解决方案吗?
xySVerma 2014年

使用#defines,当您使用#进行替换时,参数会自动用双引号引起来。在C语言中,当两个字符串在代码(如)中彼此相邻出现时"foo""bar",将"foobar"在编译时生成该字符串。因此,#define VariableName(arg) (@""#arg)将扩展VariableName(MyEnum)(@"""MyEnum")。这将导致字符串@"MyEnum"
克里斯·道格拉斯

3

给定一个枚举定义,如:

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

我们可以定义一个宏来将枚举值转换为其对应的字符串,如下所示。

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

switch块中使用的语句用于类型检查,还用于获得Xcode中的自动完成支持。

在此处输入图片说明 在此处输入图片说明


2

我有一个大型的枚举类型,我想将其转换为NSDictionary查找。我最终sed从OSX终端使用了:

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

可以理解为:'捕获行中的第一个单词并输出@(word):@“ word”,“

此正则表达式在名为“ ObservationType.h”的头文件中转换枚举,该头文件包含:

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

变成类似:

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

然后可以将其包装在使用现代Objective-C语法的方法中@{ }(如上面的@ yar1vn所述)以创建NSDictionary查找:

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

dispatch_once锅炉板只是为了确保静态变量在一个线程安全的方式初始化。

注意:我在OSX上发现sed regex表达式很奇怪-当我尝试使用它+来匹配“一个或多个”时,它不起作用,不得不求助于使用{1,}它来代替


2

我对巴里·沃克(Barry Walk)的答案使用了一种变体,按照重要性的顺序排列:

  1. 允许编译器检查缺少的case子句(如果具有默认子句则无法检查)。
  2. 使用Objective-C典型名称(而不是类似Java的名称)。
  3. 引发特定异常。
  4. 更短。

例如:

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

2

@pixel在这里添加了最出色的答案:https ://stackoverflow.com/a/24255387/1364257 请支持他!

他使用了1960年代的简洁X宏。(我为现代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];
}

而已。干净整洁。感谢@pixel!https://stackoverflow.com/users/21804/pixel


@AlexandreG,请提供您的解决方案,伙计。对某人很容易carp之以鼻。该解决方案具有明显的优点和缺点。用您的解决方案使世界变得更美好。
voiger

2

我在这里结合了几种方法。我喜欢预处理器和索引列表的想法。

没有额外的动态分配,并且由于内联,编译器可能能够优化查找。

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

1

首先,关于FormatType.JSON:JSON不是FormatType的成员,它是该类型的可能值。FormatType甚至不是复合类型-它是标量。

其次,执行此操作的唯一方法是创建映射表。在Objective-C中执行此操作的更常见方法是创建一系列引用您的“符号”的常量,以此类推NSString *FormatTypeJSON = @"JSON"


1

下面提供了一个解决方案,使添加新的枚举只需要单行编辑,类似于在枚举{}列表中添加单行的工作。

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

万一有人想阅读一下,该技术称为X-Macro。这是因为从传统上来说,FOR_EACH_GENDER()宏始终仅被称为X()。您可能想做的一件事是#undef FOR_EACH_GENDER,然后用新的含义重新定义它。
uliwitness

1

这里的每个答案基本上都说相同的事情,创建一个常规的枚举,然后使用自定义的getter在字符串之间进行切换。

我使用一个更简单,更快,更短,更干净的解决方案-使用宏!


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

然后,您可以简单地开始输入kNam...,自动完成功能将显示您想要的列表!

另外,如果您想一次处理所有名称的逻辑,则可以简单地按顺序快速枚举文字数组,如下所示:

for (NSString *kName in kNames_allNames) {}

最后,宏中的NSString强制转换可确保行为类似于typedef!


请享用!


0

许多答案都还不错。

如果您追求使用某些宏的通用Objective C解决方案...

关键特性是它使用枚举作为NSString常量静态数组的索引。数组本身被包装到一个函数中,使其更像Apple API中常见的NSStringFromXXX函数套件。

您将需要#import "NSStringFromEnum.h"在这里找到 http://pastebin.com/u83RR3Vk

[编辑]也需要#import "SW+Variadic.h"在这里找到http://pastebin.com/UEqTzYLf

示例1:使用字符串转换器完全定义一个NEW枚举typedef。

在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)

在myfile.m中:


 #import "myfile.h"

 implementation_NSString_Enum_Converters(Dispatch_chain_cmd)

使用:

NSString *NSStringFromEnumDispatch_chain_cmd(enum Dispatch_chain_cmd value);

NSStringFromEnumDispatch_chain_cmd(chain_for_c) 退货 @"chain_for_c"

  enum Dispatch_chain_cmd enumDispatch_chain_cmdFromNSString(NSString *value);

enumDispatch_chain_cmdFromNSString(@"chain_previous") 退货 chain_previous

示例2:为现有枚举提供转换例程还演示了如何使用设置字符串,以及如何重命名函数中使用的类型名。

在myfile.h中


 #import "NSStringFromEnum.h"


 #define CAEdgeAntialiasingMask_SETTINGS_PARAMS CAEdgeAntialiasingMask,mask,EdgeMask,edgeMask

 interface_NSString_Enum_Converters(CAEdgeAntialiasingMask_SETTINGS_PARAMS)

在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)

0

这里正在工作-> 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;
}

因为不允许重复的答案,所以这里是完整的解决方案 github.com/ndpiparava/ObjcEnumString
Nitin

-2

根据您的需求,您可以选择使用编译器指令来模拟您想要的行为。

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

只需记住编译器通常存在的缺点((不是安全类型,直接复制粘贴会使源文件变大)


8
我认为这行不通;–在任何#define可见的位置,您将无法使用实际的枚举值(即,当JSON替换为@"JSON"。时,将被预处理器替换,并且会导致编译器错误FormatType。)
Barry Wark,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.