Objective-C 可以打开 NSString 吗?

还有更聪明的方法来重写吗?

if ([cardName isEqualToString:@"Six"]) {
[self setValue:6];
} else if ([cardName isEqualToString:@"Seven"]) {
[self setValue:7];
} else if ([cardName isEqualToString:@"Eight"]) {
[self setValue:8];
} else if ([cardName isEqualToString:@"Nine"]) {
[self setValue:9];
}
105058 次浏览

不幸的是,他们不能。这是使用 switch 语句最好、最受欢迎的方法之一,因此希望它们能够赶上(现在) Java (和其他)的潮流!

如果您正在处理卡片名称,也许可以为每个卡片对象分配一个整数值并打开它。或者可能是枚举,它被认为是一个数字,因此可以被打开。

例如:。

typedef enum{
Ace, Two, Three, Four, Five ... Jack, Queen, King


} CardType;

这样做,Ace 等于情况0,情况2等于情况1,等等。

还有其他方法可以做到这一点,但 switch不是其中之一。

如果您只有几个字符串,就像在您的示例中一样,那么您的代码就很好。如果有很多情况,可以将字符串作为键存储在字典中,然后查找相应的值:

NSDictionary *cases = @{@"Six" : @6,
@"Seven" : @7,
//...
};


NSNumber *value = [cases objectForKey:cardName];
if (value != nil) {
[self setValue:[value intValue]];
}

遗憾的是,switch 语句只能用于基元类型。

也许最好的选择是将每个值作为一个条目存储在 NSDictionary 中。

NSDictionary *stringToNumber = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:6],@"Six",
[NSNumber numberWithInt:7],@"Seven",
[NSNumber numberWithInt:8],@"Eight",
[NSNumber numberWithInt:9],@"Nine",
nil];
NSNumber *number = [stringToNumber objectForKey:cardName];
if(number) [self setValue:[number intValue]];

Objective-c 在这方面与 c 没有什么不同,它只能开启 c 可以开启的东西(preproc def 类似于 NSInteger,NSUInteger,因为它们最终只是被 typedef 转换为整型)。

维基百科:

C 语法 :

Switch 语句根据表达式(必须是整型的)的值将控制权转移到几个语句之一。

积分类型 :

在计算机科学中,整数是整数数据类型的数据 数据类型,表示数学的某个有限子集 整数。整数数据类型可以是不同大小的,可以是 不允许包含负值。

这里有一个更聪明的写法,就是在 “拼写风格”中使用 NSNumberFormatter:

NSString *cardName = ...;


NSNumberFormatter *nf = [[NSNumberFormatter alloc] init];
[nf setNumberStyle:NSNumberFormatterSpellOutStyle];
NSNumber *n = [nf numberFromString:[cardName lowercaseString]];
[self setValue:[n intValue]];
[nf release];

请注意,数字格式化程序希望字符串是小写的,因此在将其传递给格式化程序之前,我们必须自己这样做。

你可以建立一个积木字典,像这样:

NSString *lookup = @"Hearts"; // The value you want to switch on


typedef void (^CaseBlock)();


// Squint and this looks like a proper switch!
NSDictionary *d = @{
@"Diamonds":
^{
NSLog(@"Riches!");
},
@"Hearts":
^{
self.hearts++;
NSLog(@"Hearts!");
},
@"Clubs":
^{
NSLog(@"Late night coding > late night dancing");
},
@"Spades":
^{
NSLog(@"I'm digging it");
}
};


((CaseBlock)d[lookup])(); // invoke the correct block of code

若要拥有“ default”部分,请将最后一行替换为:

CaseBlock c = d[lookup];
if (c) c(); else { NSLog(@"Joker"); }

希望苹果能教会我们一些新的技巧。

对我来说,一个简单的方法:

NSString *theString = @"item3";   // The one we want to switch on
NSArray *items = @[@"item1", @"item2", @"item3"];
int item = [items indexOfObject:theString];
switch (item) {
case 0:
// Item 1
break;
case 1:
// Item 2
break;
case 2:
// Item 3
break;
default:
break;
}

我不能在@Cris 的回答上评论 Cris 的回答,但是我想说:

@ cris 的方法有一个局限性:

Typedef 枚举不接受字母数字值

typedef enum
{
12Ace, 23Two, 23Three, 23Four, F22ive ... Jack, Queen, King


} CardType;

这里还有另外一个:

链接 Stack over flow 转到此用户答案“ user1717750”

到目前为止..

objswitch(someObject)
objcase(@"one") { // Nesting works.
objswitch(@"b")
objcase(@"a") printf("one/a");
objcase(@"b") printf("one/b");
endswitch // Any code can go here, including break/continue/return.
}
objcase(@"two") printf("It's TWO.");  // Can omit braces.
objcase(@"three",     // Can have multiple values in one case.
nil,              // nil can be a "case" value.
[self self],      // "Case" values don't have to be constants.
@"tres", @"trois") { printf("It's a THREE."); }
defaultcase printf("None of the above."); // Optional default must be at end.
endswitch

它也适用于非字符串,甚至在循环中!

for (id ifNumericWhatIsIt in @[@99, @0, @"shnitzel"])
objswitch(ifNumericWhatIsIt)
objkind(NSNumber)  printf("It's a NUMBER.... ");
objswitch([ifNumericWhatIsIt stringValue])
objcase(@"3")   printf("It's THREE.\n");
objcase(@"99")  printf("It's NINETY-NINE.\n");
defaultcase     printf("some other Number.\n");
endswitch
defaultcase printf("It's something else entirely.\n");
endswitch


It's a NUMBER.... It's NINETY-NINE.
It's a NUMBER.... some other Number.
It's something else entirely.

最好的是,有这么少的 {...}的,:的,和 ()

我有点迟到了,但是对于 如上所述回答问题来说,有一个更聪明的方法:

NSInteger index = [@[@"Six", @"Seven", @"Eight", @"Nine"] indexOfObject:cardName];
if (index != NSNotFound) [self setValue: index + 6];

请注意,indexOfObject将使用 isEqual:查找匹配项,与问题中完全一样。

有点晚了,但是对于未来的任何人来说,我可以让它为我工作

#define CASE(str) if ([__s__ isEqualToString:(str)])
#define SWITCH(s) for (NSString *__s__ = (s); ; )
#define DEFAULT
typedef enum
{
Six,
Seven,
Eight
} cardName;


- (void) switchcardName:(NSString *) param {
switch([[cases objectForKey:param] intValue]) {
case Six:
NSLog(@"Six");
break;
case Seven:
NSLog(@"Seven");
break;
case Eight:
NSLog(@"Eight");
break;
default:
NSLog(@"Default");
break;
}
}

享受编码... ..。

基于@Graham Perks 之前提出的想法,设计了一个简单的类,使字符串的切换相当简单和干净。

@interface Switcher : NSObject


+ (void)switchOnString:(NSString *)tString
using:(NSDictionary<NSString *, CaseBlock> *)tCases
withDefault:(CaseBlock)tDefaultBlock;


@end


@implementation Switcher


+ (void)switchOnString:(NSString *)tString
using:(NSDictionary<NSString *, CaseBlock> *)tCases
withDefault:(CaseBlock)tDefaultBlock
{
CaseBlock blockToExecute = tCases[tString];
if (blockToExecute) {
blockToExecute();
} else {
tDefaultBlock();
}
}


@end

你可以这样使用它:

[Switcher switchOnString:someString
using:@{
@"Spades":
^{
NSLog(@"Spades block");
},
@"Hearts":
^{
NSLog(@"Hearts block");
},
@"Clubs":
^{
NSLog(@"Clubs block");
},
@"Diamonds":
^{
NSLog(@"Diamonds block");
}
} withDefault:
^{
NSLog(@"Default block");
}
];

正确的块将根据字符串执行。

这个解决方案的要点

您可以使用宏方法来实现它:

#define CASE(str)  if ([__s__ isEqualToString:(str)])
#define SWITCH(s)  for (NSString *__s__ = (s); ; )
#define DEFAULT


SWITCH (string) {
CASE (@"TestString") {
break;
}
CASE (@"YetAnotherString") {
break;
}
CASE (@"Test") {
break;
}
DEFAULT {
break;
}
}