web-dev-qa-db-fra.com

Objective-C peut-il activer NSString?

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

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.

145
Chris

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.

118
Graham Perks

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

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]];
11
ughoavgfhw

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
7
Newyork167

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.

6
Dave DeLong

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

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 ()'

3
Alex Gray

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:

syntaxe c :

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 .

Types intégraux :

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.

3
chown

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.

1
ilya n.

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"

0
Puru

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.

Gist pour cette solution

0
Chuck Krutsinger