Преобразуйте objective-c typedef в его эквивалент строки
Предполагая, что у меня есть typedef, объявленный в моем файле .h как таковой:
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
Это действительно вопрос C, не относящийся к Objective-C (который является надмножеством языка C). Перечисления в C представлены в виде целых чисел. Таким образом, вам нужно написать функцию, которая возвращает строку с учетом значения перечисления. Есть много способов сделать это. Массив строк, так что значение enum можно использовать как индекс в массиве или структуре карты (например, 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
- это тип, а значения перечисления (например, JSON
, XML
и т.д.) - это значения, которые вы можете назначить этому типу.
Ответ 2
Вы не можете сделать это легко. В 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])
.
Ответ 3
Мое решение:
edit: я добавил еще лучшее решение в конце, используя Modern Obj-C
1.
Поместите имена в виде ключей в массиве.
Убедитесь, что индексы являются подходящими перечислениями, и в правильном порядке (в противном случае исключение).
note: 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]);
Ответ 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]);
В худшем случае - как если бы вы изменили перечисление, но забыли изменить массив имен - он вернет нуль для этого ключа.
Ответ 5
определить typedef enum в заголовке класса:
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
Мне нравится способ #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];
}
источник (источник больше не доступен)
Ответ 8
Я создал разновидность всех решений, найденных на этой странице, чтобы создать мой, это своего рода объектно-ориентированное расширение enum или
что-то.
На самом деле, если вам нужно больше, чем просто константы (т.е. целые числа), вам, вероятно, нужен модельный объект (все мы говорим о MVC, верно?)
Просто задайте себе вопрос, прежде чем использовать это, правильно ли, действительно ли вам нужен реальный объект модели, инициализированный из веб-службы, plist, базы данных SQLite или CoreData?
В любом случае сюда приходит код (MPI для "My Project Initials", все используют это или их имя, похоже):
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
Ответ 9
Улучшен ответ @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)];
}
Таким образом, когда вы измените имя записи перечисления, соответствующая строка будет изменена.
Полезно в случае, если вы не собираетесь показывать эту строку пользователю.
Ответ 10
Другое решение:
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);
Ответ 11
У меня был большой перечислимый тип, который я хотел преобразовать в поиск NSDictionary
. Я закончил использование sed
с терминала OSX следующим образом:
$ sed -E 's/^[[:space:]]{1,}([[:alnum:]]{1,}).*$/ @(\1) : @"\1",/g' ObservationType.h
который можно читать как: 'захватить первое слово на линии и вывести @(слово): @ "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
предназначена только для того, чтобы статическая переменная была инициализирована поточно-безопасным способом.
Примечание. Я нашел выражение sed regex на OSX нечетным - когда я пытался использовать +
для соответствия "одному или нескольким", он не работал, и ему пришлось прибегать к использованию {1,}
в качестве замены
Ответ 12
Я использую вариант ответа Барри-Уайга, который в порядке важности:
- Позволяет компилятору проверять отсутствие предложений case (это невозможно, если у вас есть предложение по умолчанию).
- Использует типичное имя Objective-C (а не как Java-имя).
- Вызывает определенное исключение.
- Короче.
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!
}
Ответ 13
@pixel добавил самый блестящий ответ здесь:
fooobar.com/questions/45615/...
Пожалуйста, поддержите его!
Он использует аккуратный макрос X с 1960-х годов. (Я немного изменил свой код для современного 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
Ответ 14
Я объединил здесь несколько подходов.
Мне нравится идея препроцессора и индексированного списка.
Нет никакого дополнительного динамического распределения, и из-за того, что компилятор мог бы оптимизировать поиск.
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];
}
Ответ 15
Прежде всего, что касается FormatType.JSON: JSON не является членом FormatType, это возможное значение типа. FormatType не является даже составным типом - это скаляр.
Во-вторых, единственный способ сделать это - создать таблицу сопоставления. Более общий способ сделать это в Objective-C - это создать ряд констант, относящихся к вашим "символам", поэтому у вас будет NSString *FormatTypeJSON = @"JSON"
и т.д.
Ответ 16
следующее обеспечивает такое решение, что для добавления нового перечисления требуется
только однострочное редактирование, аналогичная работа по добавлению одной строки в список enum {}.
//------------------------------------------------------------------------------
// 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);
}
}
Ответ 17
Для определения перечисления типа:
typedef NS_ENUM(NSInteger, AssetIdentifier) {
Isabella,
William,
Olivia
};
Мы можем определить макрос, чтобы преобразовать значение перечисления в соответствующую строку, как показано ниже.
#define AssetIdentifier(asset) \
^(AssetIdentifier identifier) { \
switch (identifier) { \
case asset: \
default: \
return @#asset; \
} \
}(asset)
Оператор switch
, используемый в блоке, предназначен для проверки типов, а также для получения автоматической поддержки в Xcode.
![введите описание изображения здесь]()
Ответ 18
Многие ответы на все довольно хорошие.
Если вы используете универсальное решение Objective C, которое использует некоторые макросы...
Ключевые особенности: он использует перечисление как индекс в статическом массиве констант NSString.
сам массив завернут в функцию, чтобы сделать ее более похожей на набор функций NSStringFromXXX, распространенных в API Apple.
вам нужно #import "NSStringFromEnum.h"
найти здесь
http://pastebin.com/u83RR3Vk
[EDIT]
также нуждается в #import "SW+Variadic.h"
, найденном здесь http://pastebin.com/UEqTzYLf
Пример 1: полностью определить NEW enum 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)
Ответ 19
Здесь работает → 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;
}
Ответ 20
Каждый ответ здесь в основном говорит об одном и том же: создайте регулярное перечисление, а затем используйте пользовательский метод получения для переключения между строками.
Я использую гораздо более простое решение, которое быстрее, короче и чище - с помощью макросов!
#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!
Наслаждайтесь!
Ответ 21
В зависимости от ваших потребностей вы также можете использовать директивы компилятора для имитации поведения, которое вы ищете.
#define JSON @"JSON"
#define XML @"XML"
#define Atom @"Atom"
#define RSS @"RSS"
Просто помните обычные недостатки компилятора (не безопасный тип, прямая копия-вставка делает исходный файл более крупным)