在objective-c中用字符串实现可读的switch case的最佳方法? [英] the best way to implement readable switch case with strings in objective-c?

查看:39
本文介绍了在objective-c中用字符串实现可读的switch case的最佳方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 ruby​​、javascript 等其他动态语言中,您可以这样做:

In other dynamic languages like ruby, javascript etc. you can do simply this:

switch(someString) {
    case "foo":
       //do something;
       break;
    case "bar":
       // do something else;
       break;
    default:
       // do something by default;
}

在objective-c 中,因为它是从c 语言派生而来的,所以你不能这样做.我的最佳做法是:

In objective-c, because it's derived very colsely from c language, you can't do that. My best practice for this is:

#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.但是我怎样才能最小化这个简单任务的对象分配呢?有人对此有更好的做法"吗?

It's seems to be ok, but #define makes foo and bar like a reserved word, and I can't use in my code. If I replace define constants with class constants, this problem is fixed, because in other classes I must use MyClassName before the constant name. But how can I minimize the object allocation for this simple task? Someone have a "better practice" for this?

下面的代码是我想做的,但是获取枚举或#define的值有点不舒服.因为我创建了一个只有一个输入的应用程序,我可以在其中编写字符串以获取该哈希并返回到 xcode 并设置枚举的值.所以我的问题是我不能在运行时这样做,因为 switch case 语句的主要行为......或者如果我用 NSDictionary 方式这样做 - >与这个解决方案相比,它有很多开销.

The code below is what I wanted to do, but it's a little bit unconfortable to get the values of the enum or #define. Because I created an application what have just an input where I can write the string to get that hash and go back to xcode and set the values for the enums. So my problem is I can't do that in runtime time, because of the main behavour of switch case statement... Or if I do that with that NSDictionary way -> its have a lot of overhead compared with this solution.

#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 

注意:散列函数可以在 common 命名空间的其他地方定义以在任何地方使用它,通常我为这类东西创建一个 Utils.h 或 Common.h.

NOTE: the hash function can defined elsewhere in common namespace to use it anywhere, typically I create a Utils.h or Common.h for this kind of stuff.

注意2:在真实单词"中,我们需要使用一些加密散列函数,但现在我使用了 Arash Partow 的算法来保持示例的简单性.

NOTE2: In "real word" we need to use some cryptographic hashing function, but now I used the algorithm by Arash Partow to keep the example simple.

那么,我的最后一个问题:有没有办法用预处理器以某种方式评估这些值?我认为没有,但也许?:-)

So, my final question: Is there a way to evaluate these values with the preprocessor somehow? I think no, but maybe? :-)

类似:

// !!!!!! 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>.广义常量表达式 可以做到给我.但是我还在测试中……

UPDATE: I found a "maybe solution" but it seems to be work with g++ 4.6> only. generalized constant expressions may be do it for me. But I'm still testing...

推荐答案

typedef enum {
    foo,
    bar
} FooBar;

- (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;
    }
}

这篇关于在objective-c中用字符串实现可读的switch case的最佳方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆