Может ли 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];
} 

Ответ 1

К сожалению, они не могут. Это одно из лучших и наиболее востребованных применений операторов switch, так что, надеюсь, они прыгают на (сейчас) Java (и другие) подножку!

Если вы делаете имена карт, возможно, назначьте каждому объекту карты целое значение и включите его. Или, возможно, перечисление, которое считается числом и поэтому может быть включено.

например.

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

} CardType;

Сделанный таким образом, Ace будет равен случаю 0, два как случай 1 и т.д.

Ответ 2

Вы можете создать словарь блоков, например:

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

Надеюсь, Apple научит "переключать" несколько новых трюков.

Ответ 3

Для меня приятный простой способ:

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

Ответ 4

К сожалению, операторы 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]];

Ответ 5

Есть и другие способы сделать это, но switch не является одним из них.

Если у вас есть только несколько строк, как в вашем примере, у вас есть хороший код. Если у вас много случаев, вы можете хранить строки как ключи в словаре и искать соответствующее значение:

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

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

Ответ 6

Вот более разумный способ написать это. Чтобы использовать NSNumberFormatter в "стиль написания" :

NSString *cardName = ...;

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

Обратите внимание, что число форматера хочет, чтобы строка была уменьшена, поэтому мы должны сделать это сами, прежде чем передавать ее в форматтер.

Ответ 7

Objective-c ничем не отличается от c в этом аспекте, он может включать только то, что может c (и preproc def, как NSInteger, NSUInteger, поскольку они в конечном счете просто типизированы для целочисленного типа).

Википедия:

c синтаксис:

Оператор switch приводит к тому, что управление передается одному из нескольких операторов в зависимости от значения выражения, которое должно иметь интегральный тип.

Интегральные типы:

В информатике целое число является базовым типом целочисленного типа данных, a тип данных, который представляет собой некоторое конечное подмножество математического целые числа. Интегральные типы данных могут быть разных размеров и могут или могут не допускается содержать отрицательные значения.

Ответ 8

BY 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 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 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 a NUMBER.... "); 
        objswitch([ifNumericWhatIsIt stringValue])
            objcase(@"3")   printf("It THREE.\n"); 
            objcase(@"99")  printf("It NINETY-NINE.\n"); 
            defaultcase     printf("some other Number.\n");
       endswitch
    defaultcase printf("It something else entirely.\n");
endswitch

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

Лучше всего, что SO немногие {...}, : и ()

Ответ 9

Немного поздно, но для любого в будущем я смог заставить это работать для меня

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

Ответ 10

Я опаздываю на вечеринку, но, чтобы ответить на вопрос, как указано, есть более интеллектуальный способ:

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

Обратите внимание, что indexOfObject будет искать совпадение с помощью isEqual:, точно так же, как в вопросе.

Ответ 11

Я не могу комментировать cris-ответ на @Cris, но я бы хотел сказать, что:

Существует метод LIMITATION для @cris:

typedef enum не будет принимать буквенно-цифровые значения

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

} CardType;

Итак, вот еще один:

Связать стек над потоком Перейти к этому пользовательскому ответу "user1717750"

Ответ 12

Основываясь на идее @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");
                               }
 ];

Правильный блок будет выполняться в соответствии со строкой.

Gist для этого решения

Ответ 13

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

Наслаждайтесь кодированием.....