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

发布于 2024-07-25 22:32:52 字数 475 浏览 9 评论 0原文

假设我在 .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 值传递给该方法,则会收到错误。 我缺少什么?

Assuming that I have a typedef declared in my .h file as such:

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

I would like to build a function that converts the numeric value of the typedef to a string. For example, if the message [self toString:JSON] was sent; it would return 'JSON'.

The function would look something like this:

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

Incidentally, if I try this syntax

[self toString:FormatType.JSON];

to pass the typedef value to the method, I get an error. What am I missing?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(22

喜你已久 2024-08-01 22:32:53

我的解决方案:

编辑:我在最后添加了更好的解决方案,使用 Modern Obj-C

1.
将名称作为键放入数组中。
确保索引是适当的枚举,并且顺序正确(否则例外)。
注意:names 是一个合成为 *_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.
使用现代 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]);

My solution:



edit: I've added even a better solution at the end, using Modern Obj-C



1.
Put names as keys in an array.

Make sure the indexes are the appropriate enums, and in the right order (otherwise exception).

note: names is a property synthesized as *_names*;

code was not checked for compilation, but I used the same technique in my app.

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.
Using Modern Obj-C you we can use a dictionary to tie descriptions to keys in the enum.
Order DOES NOT matter.


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


Usage (in a class instance method):

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


随波逐流 2024-08-01 22:32:53

结合 @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 。

Combining @AdamRosenfield answer, @Christoph comment and another trick to handle plain C enums I suggest:

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

In the worst case - like if you change the enum but forget to change the names array - it will return nil for this key.

枉心 2024-08-01 22:32:53

在类头中定义 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);
}

将字符串放在 Localized.strings 文件中:

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

define typedef enum in class header:

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

write a method like this in class:

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

have the strings inside Localizable.strings file:

/* IngredientType_text */
"IngredientType_0" = "Text";
/* IngredientType_audio */
"IngredientType_1" = "Audio";
/* IngredientType_video */
"IngredientType_2" = "Video";
/* IngredientType_image */
"IngredientType_3" = "Image";
本王不退位尔等都是臣 2024-08-01 22:32:53

我将使用编译器的 # string 标记(以及宏以使其更加紧凑):

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

I would use the compiler's # string token (along with macros to make it all more compact):

#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
}
掩于岁月 2024-08-01 22:32:53

我喜欢 #define 的做法:

// 将其放入 .h 文件中,@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];
}

来源(来源不再可用)

I like the #define way of doing this:

// Place this in your .h file, outside the @interface block

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 (source no longer available)

爱要勇敢去追 2024-08-01 22:32:53

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

事实上,如果您需要的不仅仅是常量(即整数),您可能需要一个模型对象(我们都在谈论 MVC,对吧?)

在使用它之前先问自己这个问题,我是对的,不是吗?事实上,需要一个真正的模型对象,从 webservice、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

I made a sort of mix of all solutions found on this page to create mine, it's a kind of object oriented enum extension or
something.

In fact if you need more than just constants (i.e. integers), you probably need a model object (We're all talking about MVC, right?)

Just ask yourself the question before using this, am I right, don't you, in fact, need a real model object, initialized from a webservice, a plist, an SQLite database or CoreData ?

Anyway here comes the code (MPI is for "My Project Initials", everybody use this or their name, it seems) :

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

And 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
﹏半生如梦愿梦如真 2024-08-01 22:32:53

另一个解决方案:

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

Another solution:

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

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

In your method you can use:

NSString *operationCheck = AMZCartServiceOperationValue(operation);
随梦而飞# 2024-08-01 22:32:53

通过删除字符串依赖项改进了 @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)];
}

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

Improved @yar1vn answer by dropping string dependency:

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

Thus when you'll change enum entry name corresponding string will be changed.
Useful in case if you are not going to show this string to user.

泪之魂 2024-08-01 22:32:53

@pixel在这里添加了最精彩的答案:
https://stackoverflow.com/a/24255387/1364257
请大家为他点赞吧!

他使用 20 世纪 60 年代简洁的 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

@pixel added the most brilliant answer here:
https://stackoverflow.com/a/24255387/1364257
Please, upvote him!

He uses the neat X macro from the 1960's. (I've changed his code a bit for the modern 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];
}

That's it. Clean and neat.
Thanks to @pixel! https://stackoverflow.com/users/21804/pixel

这样的小城市 2024-08-01 22:32:53

给定一个枚举定义,例如:

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

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

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

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

输入图片此处描述
输入图片此处描述

Given an enum definition like:

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

We can define a macro to convert an enum value to its corresponding string, as shown below.

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

The switch statement used in the block is for type checking, and also to get the auto-complete support in Xcode.

enter image description here
enter image description here

单调的奢华 2024-08-01 22:32:53

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

$ 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 正则表达式很奇怪 - 当我尝试使用 + 来匹配“一个或多个”时,它不起作用,不得不求助于使用 {1,} 作为替代品

I had a large enumerated type I wanted to convert it into an NSDictionary lookup. I ended up using sed from OSX terminal as:

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

which can be read as: 'capture the first word on the line and output @(word) : @"word",'

This regex converts the enum in a header file named 'ObservationType.h' which contains:

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

into something like:

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

which can then be wrapped in a method using modern objective-c syntax @{ } (as explained by @yar1vn above) to create a NSDictionary lookup :

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

The dispatch_once boiler-plate is just to ensure that the static variable is initialised in a thread-safe manner.

Note: I found the sed regex expression on OSX odd - when I tried to use + to match 'one or more' it didn't work and had to resort to using {1,} as a replacement

千年*琉璃梦 2024-08-01 22:32:53

我使用 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!
}

I use a variation on Barry Walk's answer, that in order of importance:

  1. Allows the compiler to check for missing case clauses (it can't if you have a default clause).
  2. Uses an Objective-C typical name (rather than a Java like name).
  3. Raises a specific exception.
  4. Is shorter.

EG:

- (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!
}
森林迷了鹿 2024-08-01 22:32:53

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

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

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

I combined several approaches here.
I like the idea of the preprocessor and the indexed list.

There's no extra dynamic allocation, and because of the inlining the compiler might be able to optimize the lookup.

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];
}
指尖微凉心微凉 2024-08-01 22:32:53

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

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

First of all, with regards to FormatType.JSON: JSON is not a member of FormatType, it's a possible value of the type. FormatType isn't even a composite type — it's a scalar.

Second, the only way to do this is to create a mapping table. The more common way to do this in Objective-C is to create a series of constants referring to your "symbols", so you'd have NSString *FormatTypeJSON = @"JSON" and so on.

思念满溢 2024-08-01 22:32:53

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

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

the following provides a solution such that to add a new enum requires
only a one-line edit, similar work to adding a single line in an enum {} list.

//------------------------------------------------------------------------------
// 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);
    }
}
满意归宿 2024-08-01 22:32:53

这里的每个答案基本上都说同样的事情,创建一个常规枚举,然后使用自定义 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!


享受!

Every answer here basically says the same thing, create a regular enum and then use a custom getter to switch between strings.

I employ a much simpler solution that is faster, shorter, and cleaner—using 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])

Then you can simply start to type kNam... and autocomplete will display the lists you desire!

Additionally, if you want to handle logic for all the names at once you can simply fast enumerate the literal array in order, as follows:

for (NSString *kName in kNames_allNames) {}

Lastly, the NSString casting in the macros ensures behavior similar to typedef!


Enjoy!

ゞ记忆︶ㄣ 2024-08-01 22:32:53

我想我刚刚创建了最优雅的方法来解决这个问题。
(受到 @AdamRosenfield 的启发)

例如,您可以像这样声明枚举:

typedef NS_ENUM(int, MyEnum) {
    MyEnumDefault,
    MyEnumOff,
    MyEnumOn,
    MyEnumMixed,
};

static NSString * const __SGEnumMap_MyEnum[] = {
    [MyEnumDefault] = @"default",
    [MyEnumOff] = @"off",
    [MyEnumOn] = @"on",
    [MyEnumMixed] = @"mixed"
};
    
SGENUM_DEFINE_ToString(MyEnum)
SGENUM_DEFINE_FromString(MyEnum)

然后,您将获得两个函数在枚举和字符串之间进行转换:

NSString *result = MyEnumToString(MyEnumOn); 
NSLog(@"%@", result);
// on
    
MyEnum value = MyEnumFromString(@"off", -1); // -1 as the default value
NSLog(@"%d", result);
// 1

是不是很酷? 以下是神奇的宏:

#define SGENUM_DEFINE_ToString(name) NS_INLINE NSString *name##ToString(name value){\
    int count = sizeof(__SGEnumMap_##name) / sizeof(NSString *);\
    if (value > count || value < 0) return nil;\
    return __SGEnumMap_##name[value];\
}

#define SGENUM_DEFINE_FromString(name) NS_INLINE name name##FromString(NSString *input, int defaultValue) {\
    int count = sizeof(__SGEnumMap_##name) / sizeof(NSString *);\
    for (int i = 0; i < count; i++) {\
        NSString *str = __SGEnumMap_##name[i];\
        if ([str isEqual:input]) {\
            return i;\
        }\
    }\
    return defaultValue;\
}

I think I just created the most elegant approach to solve this.
(inspired by @AdamRosenfield)

For example, you may declare the enum like this:

typedef NS_ENUM(int, MyEnum) {
    MyEnumDefault,
    MyEnumOff,
    MyEnumOn,
    MyEnumMixed,
};

static NSString * const __SGEnumMap_MyEnum[] = {
    [MyEnumDefault] = @"default",
    [MyEnumOff] = @"off",
    [MyEnumOn] = @"on",
    [MyEnumMixed] = @"mixed"
};
    
SGENUM_DEFINE_ToString(MyEnum)
SGENUM_DEFINE_FromString(MyEnum)

Then, you get the two functions to convert between enums and strings:

NSString *result = MyEnumToString(MyEnumOn); 
NSLog(@"%@", result);
// on
    
MyEnum value = MyEnumFromString(@"off", -1); // -1 as the default value
NSLog(@"%d", result);
// 1

Is that cool? Here are the magic macros:

#define SGENUM_DEFINE_ToString(name) NS_INLINE NSString *name##ToString(name value){\
    int count = sizeof(__SGEnumMap_##name) / sizeof(NSString *);\
    if (value > count || value < 0) return nil;\
    return __SGEnumMap_##name[value];\
}

#define SGENUM_DEFINE_FromString(name) NS_INLINE name name##FromString(NSString *input, int defaultValue) {\
    int count = sizeof(__SGEnumMap_##name) / sizeof(NSString *);\
    for (int i = 0; i < count; i++) {\
        NSString *str = __SGEnumMap_##name[i];\
        if ([str isEqual:input]) {\
            return i;\
        }\
    }\
    return defaultValue;\
}
稍尽春風 2024-08-01 22:32:53

很多答案都还不错。

如果您正在寻找使用一些宏的通用 Objective C 解决方案...

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

您需要在此处找到#import "NSStringFromEnum.h"
http://pastebin.com/u83RR3Vk

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

示例 1:使用字符串转换器完全定义一个新的枚举 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)

Many answers all fairly good.

If you are after a generic, Objective C solution that uses some macros...

Key feature is it uses the enum as an index into a static array of NSString constants.
the array itself is wrapped into a function to make it more like the suite of NSStringFromXXX functions prevalent in the Apple APIs.

you will need to #import "NSStringFromEnum.h" found here
http://pastebin.com/u83RR3Vk

[EDIT]
also needs #import "SW+Variadic.h" found here http://pastebin.com/UEqTzYLf

Example 1 : completely define a NEW enum typedef, with string converters.

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

in myfile.m:


 #import "myfile.h"

 implementation_NSString_Enum_Converters(Dispatch_chain_cmd)

to use :

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") returns chain_previous

Example 2: provide conversion routines for an existing enum
also demonstrates using a settings string, and renaming the typename used in the functions.

in myfile.h


 #import "NSStringFromEnum.h"


 #define CAEdgeAntialiasingMask_SETTINGS_PARAMS CAEdgeAntialiasingMask,mask,EdgeMask,edgeMask

 interface_NSString_Enum_Converters(CAEdgeAntialiasingMask_SETTINGS_PARAMS)

in 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)
笑饮青盏花 2024-08-01 22:32:53

这是工作 -> 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;
}

Here is working -> 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;
}
情绪少女 2024-08-01 22:32:53

根据您的需要,您也可以使用编译器指令来模拟您正在寻找的行为。

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

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

Depending on your needs, you could alternatively use compiler directives to simulate the behaviour you are looking for.

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

Just remember the usual compiler shortcomings, (not type safe, direct copy-paste makes source file larger)

如梦初醒的夏天 2024-08-01 22:32:52

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

- (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 等)是您可以分配给该类型的值。

This is really a C question, not specific to Objective-C (which is a superset of the C language). Enums in C are represented as integers. So you need to write a function that returns a string given an enum value. There are many ways to do this. An array of strings such that the enum value can be used as an index into the array or a map structure (e.g. an NSDictionary) that maps an enum value to a string work, but I find that these approaches are not as clear as a function that makes the conversion explicit (and the array approach, although the classic C way is dangerous if your enum values are not continguous from 0). Something like this would work:

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

Your related question about the correct syntax for an enum value is that you use just the value (e.g. JSON), not the FormatType.JSON sytax. FormatType is a type and the enum values (e.g. JSON, XML, etc.) are values that you can assign to that type.

甚是思念 2024-08-01 22:32:52

你不能轻易做到。 在 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])

You can't do it easily. In C and Objective-C, enums are really just glorified integer constants. You'll have to generate a table of names yourself (or with some preprocessor abuse). For example:

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

The danger of this approach is that if you ever change the enum, you have to remember to change the array of names. You can solve this problem with some preprocessor abuse, but it's tricky and ugly.

Also note that this assumes you have a valid enum constant. If you have an integer value from an untrusted source, you additionally need to do a check that your constant is valid, e.g. by including a "past max" value in your enum, or by checking if it's less than the array length, sizeof(FormatType_toString) / sizeof(FormatType_toString[0]).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文