Может ли Objective-C включить NSString? - PullRequest
162 голосов
/ 17 ноября 2011

Есть ли более разумный способ переписать это?

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

Ответы [ 13 ]

143 голосов
/ 17 ноября 2011

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

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

, например

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

} CardType;

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

118 голосов
/ 16 апреля 2012

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

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 будетнаучите «переключать» несколько новых трюков.

76 голосов
/ 10 сентября 2013

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

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;
}
11 голосов
/ 17 ноября 2011

К сожалению, операторы 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]];
7 голосов
/ 14 сентября 2016

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

#define CASE(str) if ([__s__ isEqualToString:(str)])
#define SWITCH(s) for (NSString *__s__ = (s); ; )
#define DEFAULT
6 голосов
/ 17 ноября 2011

Вот более разумный способ написать это.Необходимо использовать NSNumberFormatter в «стиле изложения» :

NSString *cardName = ...;

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

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

6 голосов
/ 17 ноября 2011

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

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

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

NSNumber *value = [cases objectForKey:cardName];
if (value != nil) {
    [self setValue:[value intValue]];
}
3 голосов
/ 25 октября 2013

BY FAR .. Мой ЛЮБИМЫЙ "ObjC Add-On" равен 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

И он работает с не строками, ТОО ... в циклах, даже!

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 голосов
/ 17 ноября 2011

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

Википедия:

c синтаксис :

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

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

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

1 голос
/ 05 декабря 2013

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

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

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

...