В других динамических языках, таких как ruby, javascript и т.д., вы можете сделать это просто:
switch(someString) {
case "foo":
//do something;
break;
case "bar":
// do something else;
break;
default:
// do something by default;
}
В objective-c, потому что он вывел очень colsely из c-языка, вы не можете этого сделать. Моя лучшая практика для этого:
#import "CaseDemo.h"
#define foo 1
#define bar 2
static NSMutableDictionary * cases;
@implementation CaseDemo
- (id)init
{
self = [super init];
if (self != nil) {
if (cases == nil) {
// this dict can be defined as a class variable
cases = [[NSMutableDictionary alloc] initWithCapacity:2];
[cases setObject:[NSNumber numberWithInt:foo] forKey:@"foo"];
[cases setObject:[NSNumber numberWithInt:bar] forKey:@"bar"];
}
}
return self;
}
- (void) switchFooBar:(NSString *) param {
switch([[cases objectForKey:param] intValue]) {
case foo:
NSLog(@"its foo");
break;
case bar:
NSLog(@"its bar");
break;
default:
NSLog(@"its default");
break;
}
}
@end
Кажется, все в порядке, но #define делает foo и bar как зарезервированное слово, и я не могу использовать его в своем коде. Если я заменил константы констант на константы класса, эта проблема будет исправлена, потому что в других классах я должен использовать MyClassName перед именем константы. Но как я могу свести к минимуму распределение объектов для этой простой задачи? У кого-то есть "лучшая практика" для этого?
EDIT: Код ниже - это то, что я хотел сделать, но немного неудобно получать значения enum или #define. Потому что я создал приложение, у которого есть только вход, где я могу написать строку для получения этого хеша и вернуться к xcode и установить значения для перечислений. Поэтому моя проблема заключается в том, что я не могу этого сделать во время выполнения из-за основного поведения оператора case switch. Или если я делаю это с помощью этого пути NSDictionary → у него много накладных расходов по сравнению с этим решением.
#import "CaseDemo.h"
typedef enum {
foo = 1033772579,
bar = -907719821
} FooBar;
unsigned int APHash(NSString* s)
{
const char* str = [s UTF8String];
unsigned int len = [s length];
unsigned int hash = 0xAAAAAAAA;
unsigned int i = 0;
for(i = 0; i < len; str++, i++)
{
hash ^= ((i & 1) == 0) ? ( (hash << 7) ^ (*str) * (hash >> 3)) :
(~((hash << 11) + ((*str) ^ (hash >> 5))));
}
return hash;
}
@implementation CaseDemo
- (void) switchFooBar:(NSString *) param {
switch(APHash(param)) {
case foo:
NSLog(@"its foo");
break;
case bar:
NSLog(@"its bar");
break;
default:
NSLog(@"its default");
break;
}
}
@end
ПРИМЕЧАНИЕ. хеш-функция может быть определена в другом пространстве общего пространства имен, чтобы использовать ее в любом месте, как правило, я создаю Utils.h или Common.h для такого рода материалов.
ПРИМЕЧАНИЕ2: В "реальном слове" нам нужно использовать некоторую криптографическую хэширующую функцию, но теперь я использовал алгоритм Араша Партоу, чтобы упростить пример.
Итак, мой последний вопрос: Есть ли способ оценить эти значения с помощью препроцессора? Думаю, нет, но, может быть?: -)
Что-то вроде:
// !!!!!! I know this code is not working, I don't want comments about "this is wrong" !!!!
// I want a solution to invoke method with preprocessor, or something like that.
typedef enum {
foo = APHash(@"foo"),
bar = APHash(@"bar")
} FooBar;
UPDATE. Я нашел "возможно решение", но, похоже, работает только с g++ 4.6 > . обобщенные константные выражения могут сделать это для меня. Но я все еще тестирую...