假设我在.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值传递给方法,我收到一个错误.我错过了什么?
这实际上是一个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.JSON
sytax.FormatType
是一种类型,枚举值(例如JSON
,XML
等)是您可以分配给该类型的值.
你不能轻易做到.在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])
.
我的解决方案:
编辑:我在最后使用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]);
结合@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.
在类头中定义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";
我会使用编译器的#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 }
我喜欢#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]; }
来源(来源不再可用)
我把这个页面上的所有解决方案混合在一起创建我的,它是一种面向对象的枚举扩展或其他东西.
事实上,如果你需要的不仅仅是常量(即整数),你可能需要一个模型对象(我们都在谈论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
另一种方案:
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);