当前位置:  开发笔记 > 编程语言 > 正文

将objective-c typedef转换为其等效字符串

如何解决《将objective-ctypedef转换为其等效字符串》经验,为你挑选了9个好方法。

假设我在.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值传递给方法,我收到一个错误.我错过了什么?



1> Barry Wark..:

这实际上是一个C问题,不是Objective-C特有的(它是C语言的超集).C中的枚举表示为整数.因此,您需要编写一个函数,该函数返回给定枚举值的字符串.有很多方法可以做到这一点.一个字符串数组,使得枚举值可以用作数组的索引或映射结构(例如a 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.JSONsytax.FormatType是一种类型,枚举值(例如JSON,XML等)是您可以分配给该类型的值.



2> Adam Rosenfi..:

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


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

3> Yariv Nissim..:

我的解决方案:

编辑:我在最后使用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.
使用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]);



请注意,每次调用`+ [typeDisplayNames]`时,都会重新创建字典.如果它只被调用几次就可以了,但是如果多次调用,这将变得非常昂贵.一个更好的解决方案可能是使字典成为单例,因此它只创建一次并保留在内存中.经典内存与CPU难题.

4> 小智..:

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



5> kitschmaster..:

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



6> 小智..:

我会使用编译器的#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
}



7> lindon fox..:

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

来源(来源不再可用)


如果用错误的值调用,则太脆弱而且太致命

8> dulgan..:

我把这个页面上的所有解决方案混合在一起创建我的,它是一种面向对象的枚举扩展或其他东西.

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

在使用它之前问问自己这个问题,我是对的,不是吗,实际上,你需要一个真正的模型对象,从webservice,plist,SQLite数据库或CoreData初始化?

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

MyWonderfulType.h :

typedef NS_ENUM(NSUInteger, MPIMyWonderfulType) {
    MPIMyWonderfulTypeOne = 1,
    MPIMyWonderfulTypeTwo = 2,
    MPIMyWonderfulTypeGreen = 3,
    MPIMyWonderfulTypeYellow = 4,
    MPIMyWonderfulTypePumpkin = 5
};

#import 

@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



9> 小智..:

另一种方案:

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

推荐阅读
雨天是最美
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有