В других динамических языках, таких как ruby, javascript и т. Д., Вы можете просто сделать это:
switch(someString) {
case "foo":
//do something;
break;
case "bar":
// do something else;
break;
default:
// do something by default;
}
В объекте-c, поскольку он очень похож на язык 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 перед именем константы. Но как я могу минимизировать выделение объектов для этой простой задачи? У кого-то есть "лучшая практика" для этого?
РЕДАКТИРОВАТЬ: Моя лучшая практика для этого:
#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 перед именем константы. Но как я могу минимизировать выделение объектов для этой простой задачи? У кого-то есть "лучшая практика" для этого?
РЕДАКТИРОВАТЬ: Моя лучшая практика для этого:
#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 перед именем константы. Но как я могу минимизировать выделение объектов для этой простой задачи? У кого-то есть "лучшая практика" для этого?
РЕДАКТИРОВАТЬ: Приведенный ниже код - это то, что я хотел сделать, но получить значения перечисления или #define немного неудобно. Потому что я создал приложение, у которого есть только ввод, где я могу написать строку, чтобы получить этот хеш, вернуться к xcode и установить значения для перечислений. Итак, моя проблема в том, что я не могу сделать это во время выполнения из-за основного поведения оператора switch case ... Или, если я сделаю это с помощью этого способа 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;
ОБНОВЛЕНИЕ : Я нашел "возможно решение", но похоже, работает только с g ++ 4.6>. обобщенные константные выражения могут сделать это за меня. Но я все еще тестирую ...