Objective-C가 NSString을 전환 할 수 있습니까?


166

이것을 다시 쓰는 더 지능적인 방법이 있습니까?

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

1
아니요, 스위치는 int / bool / char / etc 유형에서만 작동합니다.
chown

이 질문은 한 시간 전에 게시이 하나 (다소 유사하다 stackoverflow.com/questions/8161319/... )
마이클 Dautermann

3
여러 가지 방법이 있습니다. 예를 들어 값으로 배열을로드하고 배열에서 일치 항목을 검색하십시오. 매우 효율적은 아니지만 코드 중복을 줄입니다.
핫 릭

4
참고로, Apple의 새로운 언어 (Swift)는 이제 switch 문에서 문자열을 비교할 수 있습니다!
jaredsmith 2016 년

4
스위프트로 전환;)
tothemario

답변:


147

불행히도 그들은 할 수 없습니다. 이것은 스위치 문을 가장 잘 활용 한 것 중 하나이므로 (현재) Java (및 기타) 악 대차를 뛰어 넘을 수 있기를 바랍니다.

카드 이름을 사용하는 경우 각 카드 객체에 정수 값을 할당하고 켜십시오. 또는 숫자로 간주되어 전환 될 수있는 열거 형입니다.

예 :

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

} CardType;

이 방법으로 완료하면 Ace는 사례 0과 같고 사례 1과 같이 2입니다.


4
@abbood enum에 대한 자세한 내용은 Mattt Thompson의 NS_ENUM & NS_OPTIONS 게시를 참조하십시오 .
Basil Bourque

@abbood 귀하의 의견은 무슨 뜻입니까? 이건 나쁜 대답이지만 나에게는 괜찮은 것 같습니다. 설명해 주시겠습니까?
Alan Andrade

내가 이해하는 것처럼, 예를 들어 다음 CardType과 같이 동봉 할 수 없습니다 @"".[CardType isEqualToString:@"Three"]
Adromil Balais

120

다음과 같이 블록 사전을 설정할 수 있습니다.

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

'기본'섹션을 가지려면 마지막 줄을 다음으로 바꾸십시오.

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

애플이 몇 가지 새로운 트릭을 '전환'할 수 있기를 바랍니다.


35
이것이 정말 불쾌한 지 정말 멋진 지 알 수 없습니다. 이 일을 생각하지 않았을 것입니다, 감사합니다.
endy

2
우리가 이와 같은 이상한 일을하는 동안 블록 객체의 NSString 키로 가득 찬 NSDictionary를 래핑 한 다음 기본 경우에 다른 블록을 제공하는 클래스를 만들어보십시오. 첨자 표기법을 지원하도록 할 수도 있습니다.
ArtOfWarfare 2016 년

1
추가 포인트 당신은이에 대한 NSDictionary와 서브 클래스를 만들 경우 : P
CommaToast

2
후드 아래에서 C #이 큰 스위치 문에 대해 수행하는 방식입니다.
행크 슐츠

78

나를 위해, 좋은 쉬운 방법 :

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

1
나는 이것을 좋아한다. 이 문제에 대한 답을 찾고자하는 대부분의 요구에 부응하며, 비슷한 스위치가 자바 스크립트에서 사용하는 것보다 훨씬 많은 타이핑이 필요하지 않으며 사람이 읽을 수 있습니다.
ew parris

4
이 핵을 JS 스위치와 비교하지 않을 것입니다. 다음 프로그래머가 item1과 item2 사이에 항목을 추가하면 어떻게됩니까? 버그 도입 가능성이 너무
Aras

그것의 좋은 해킹, 그래서 나는 당신에게 노력에 대한 엄지 손가락을 포기 :)
Aras

@Aras 만약 다음 프로그래머가 새로운 엔트리를 추가해야한다면, 그것을 처리하기 위해 끝에 새로운 case 문으로 배열의 끝에 추가 할 것입니다. 따라서 배열에서 @ "item3"뒤에 @ "item0"을 추가 한 다음 사례 3을 추가하여 처리 할 수 ​​있습니다.
sbonkosky

1
나는 당신의 방식을 완전히 좋아합니다. 매우 깔끔합니다. 카테고리를 작성 중이며 문자열이있는 동안 UIColor를 반환해야합니다.
Alix

11

불행히도 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]];

8

조금 늦었지만 미래의 누군가를 위해 나는 이것을 위해 나를 도울 수있었습니다.

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

이건 재미 있네. 더 정교하게 할 수 있습니까?
Chen Li Yong

6

그것을 쓰는 더 지능적인 방법이 있습니다. "맞춤법 스타일"NSNumberFormatter 에서 를 사용합니다 .

NSString *cardName = ...;

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

숫자 포맷터는 문자열을 소문자로 원하므로 포맷터로 전달하기 전에 직접해야합니다.


5

다른 방법이 있지만 switch그중 하나가 아닙니다.

예제와 같이 몇 개의 문자열 만 있으면 코드가 좋습니다. 많은 경우에 문자열을 사전에 키로 저장하고 해당 값을 찾을 수 있습니다.

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

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

4

FAR.에 의해 내 좋아하는 "ObjC 애드온"은ObjectMatcher

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

그리고 그것은 문자열이 아닌, TOO ... 루프에서도 작동합니다!

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.

무엇보다도, {...}', :'및 ()'가 거의 없습니다.


3

Objective-c는이 측면에서 c와 다르지 않으며 c가 할 수있는 것만 전환 할 수 있습니다.

위키 백과 :

c 구문 :

switch 문은 표현식 이 정수형이어야 하는 표현식의 값에 따라 여러 명령문 중 하나로 제어를 전송 합니다 .

일체형 :

컴퓨터 과학에서 정수는 정수 데이터 형식의 데이텀으로, 수학 정수의 일부 유한 하위 집합을 나타내는 데이터 형식입니다. 정수 데이터 유형은 크기가 다를 수 있으며 음수 값을 포함하거나 포함하지 않을 수 있습니다.


2

나는 파티에 늦었지만 언급 된 질문대답하기 위해보다 지능적인 방법이 있습니다.

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

참고 indexOfObject사용하여 경기를 찾습니다 isEqual:정확하게 문제로.


2

앞서 게시 한 @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");
                               }
 ];

문자열에 따라 올바른 블록이 실행됩니다.

이 솔루션의 요지


0

@Cris 답변에 대한 cris의 답변에 대해서는 언급 할 수 없지만 다음과 같이 말하고 싶습니다.

@cris의 방법에는 제한이 있습니다.

typedef 열거 형은 영숫자 값을 사용하지 않습니다

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

} CardType;

여기 또 다른 것이 있습니다 :

Flow Stack over flow 이 사용자 답변으로 이동 "user1717750"


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

코딩 즐기기 .....

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.