Existe-t-il un moyen plus intelligent de réécrire cela?
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];
}
Malheureusement, ils ne peuvent pas. Il s’agit de l’une des utilisations les meilleures et les plus recherchées des instructions switch. Nous espérons donc qu’elles sauteront dans le mouvement (maintenant) Java (et d’autres)!
Si vous nommez des cartes, attribuez peut-être une valeur entière à chaque objet de carte et activez-la. Ou peut-être une énumération, qui est considérée comme un nombre et peut donc être activée.
par exemple.
typedef enum{
Ace, Two, Three, Four, Five ... Jack, Queen, King
} CardType;
Fait de cette façon, As serait égal à cas 0, deux comme cas 1, etc.
Vous pouvez créer 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!
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
Pour avoir une section 'default', remplacez la dernière ligne par:
CaseBlock c = d[lookup];
if (c) c(); else { NSLog(@"Joker"); }
Espérons que Apple apprendra à "changer" quelques nouveaux trucs.
Pour moi, un moyen simple et agréable:
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;
}
Malheureusement, les instructions switch ne peuvent être utilisées que sur des types primitifs. Vous avez cependant quelques options en utilisant des collections.
La meilleure option serait probablement de stocker chaque valeur en tant qu'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]];
Un peu en retard mais pour tout le monde à l'avenir, j'ai pu obtenir que cela fonctionne pour moi
#define CASE(str) if ([__s__ isEqualToString:(str)])
#define SWITCH(s) for (NSString *__s__ = (s); ; )
#define DEFAULT
Voici la façon la plus intelligente d’écrire cela. C'est utiliser un NSNumberFormatter
dans le "style d'épellation" :
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 formateur de nombres veut que la chaîne soit en minuscule, nous devons donc le faire nous-mêmes avant de la transmettre au formateur.
Il y a d'autres façons de le faire, mais switch
n'en fait pas partie.
Si vous n'avez que quelques chaînes, comme dans votre exemple, le code que vous avez est correct. Si vous avez plusieurs cas, vous pouvez stocker les chaînes en tant que clés dans un dictionnaire et rechercher la valeur correspondante:
NSDictionary *cases = @{@"Six" : @6,
@"Seven" : @7,
//...
};
NSNumber *value = [cases objectForKey:cardName];
if (value != nil) {
[self setValue:[value intValue]];
}
BY FAR .. mon "add-on ObjC" préféré est 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
ET cela fonctionne avec les non-chaînes, TROP ... dans les boucles, même!
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.
Le meilleur de tous, il y a SO _ _ quelques {...}
', :
et ()
'
Objective-c n'est pas différent de c sous cet aspect, il ne peut basculer que sur ce que c peut (et les paramètres de préproc, comme NSInteger, NSUInteger, puisqu'ils sont finalement simplement typés et convertis en un type intégral).
Wikipédia:
L'instruction switch provoque le transfert du contrôle vers l'une de plusieurs instructions en fonction de la valeur d'une expression, laquelle doit être de type intégral .
En informatique, un entier est une donnée de type de données intégrale, un type de données qui représente un sous-ensemble fini des entiers mathématiques. Les types de données intégrales peuvent être de tailles différentes et peuvent ou non contenir des valeurs négatives.
Je suis un peu en retard à la fête, mais pour répondez à la question comme indiqué, il existe un moyen plus intelligent:
NSInteger index = [@[@"Six", @"Seven", @"Eight", @"Nine"] indexOfObject:cardName];
if (index != NSNotFound) [self setValue: index + 6];
Notez que indexOfObject
cherchera la correspondance en utilisant isEqual:
, exactement comme dans la question.
Je ne peux pas commenter la réponse de cris à la réponse @Cris, mais j'aimerais dire ceci:
Il y a une LIMITATION pour la méthode de @ cris:
typedef enum ne prendra pas de valeurs alphanumériques
typedef enum
{
12Ace, 23Two, 23Three, 23Four, F22ive ... Jack, Queen, King
} CardType;
Alors voici un autre:
Link Stack over flow Aller à la réponse de cet utilisateur "user1717750"
En s’appuyant sur l’idée de @Graham Perks publiée plus tôt, a conçu une classe simple permettant de changer de chaîne de manière assez simple et propre.
@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
Vous l'utiliseriez comme ceci:
[Switcher switchOnString:someString
using:@{
@"Spades":
^{
NSLog(@"Spades block");
},
@"Hearts":
^{
NSLog(@"Hearts block");
},
@"Clubs":
^{
NSLog(@"Clubs block");
},
@"Diamonds":
^{
NSLog(@"Diamonds block");
}
} withDefault:
^{
NSLog(@"Default block");
}
];
Le bloc correct sera exécuté en fonction de la chaîne.