172 votes

Pouvez Objective-C commutateur sur NSString?

Est-il une manière plus intelligente de réécrire ce?

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

151voto

Chris Points 3445

Malheureusement, ils ne le peuvent pas. C'est l'un des meilleurs et des plus recherchés après les utilisations des instructions de commutation, donc j'espère qu'ils hop sur le (désormais) Java (et d'autres) train en marche!

Si vous faites des noms de cartes, peut-être attribuer à chaque carte de l'objet une valeur entière et l'allumer. Ou peut-être un enum, qui est considéré comme un nombre et peut donc être commuté sur.

par exemple

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

} CardType;

Fait de cette façon, Ace serait égal à 0, Deux dans le cas 1, etc.

124voto

Graham Perks Points 8103

Vous pourriez mettre en place un dictionnaire de blocs, comme ceci:

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

typedef void (^CaseBlock)();

// Squint and this looks like a proper switch block!
// New ObjC syntax makes the NSDictionary creation cleaner.
NSDictionary *d = @{
    @"Diamonds": 
    ^{ 
        NSLog(@"Riches!"); 
    },
    @"Hearts":
    ^{ 
        self.hearts++;
        NSLog(@"Hearts!"); 
    },
    @"Clubs":
    ^{ 
        NSLog(@"Clubs"); 
    },
    @"Spades":
    ^{ 
        NSLog(@"Spades"); 
    }
};

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

Cette alternative simple ne prend pas en charge "par défaut", ni de l'automne, et il va se bloquer si la valeur de la recherche n'est pas trouvé. Afin d'éviter l'accident, et avoir un peu de code par défaut, la dernière ligne pourrait être:

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

Espérons qu'Apple va enseigner "switch" quelques nouveaux trucs, que cette solution n'est pas vraiment jolie (si réalisable).

Edit: j'ai remplacé cette ancienne syntaxe de code avec la nouvelle syntaxe ci-dessus. L'ancienne syntaxe:

NSDictionary *d = [NSDictionary dictionaryWithObjectsAndKeys:
                   ^() { NSLog(@"case 1"); }, @"1",
                   ^() { NSLog(@"case 2"); }, @"2",
                   ^() { NSLog(@"case 3"); }, @"3",
                   ^() { NSLog(@"case 4"); }, @"4",
                   nil];

85voto

sbonkosky Points 890

Pour moi, une belle façon très simple:

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

11voto

ughoavgfhw Points 28400

Malheureusement, les instructions switch peut être utilisé uniquement sur les types primitifs. Vous avez quelques options à l'aide de collections, pourtant.

Probablement la meilleure option serait de stocker chaque valeur comme une entrée dans un 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]];

6voto

Dave DeLong Points 156978

Ici, c'est le plus intelligent de la façon d'écrire. C'est pour utiliser un NSNumberFormatter dans le "spell-out de style":

NSString *cardName = ...;

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

Notez que le numéro de formateur veut la chaîne à être mis en minuscule, donc nous devons le faire nous-mêmes avant de le transmettre au formateur.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X