¿Puede Objective-C activar NSString?


¿Hay una forma más inteligente de reescribir esto?

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];
} 
Author: JAM, 2011-11-17

13 answers

Desafortunadamente no pueden. Esta es una de las mejores y más buscadas utilizaciones de sentencias switch, así que esperamos que se suban al (ahora) carro de Java (y otros)!

Si está haciendo nombres de tarjeta, tal vez asigne a cada objeto de tarjeta un valor entero y active eso. O tal vez una enumeración, que se considera como un número y por lo tanto se puede cambiar.

Por ejemplo

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

} CardType;

Hecho de esta manera, Ace sería igual al caso 0, Dos como caso 1, etc.

 137
Author: Chris,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-11-17 03:30:25

Puedes configurar un diccionario de bloques, así:

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

Para tener una sección 'predeterminada', reemplace la última línea con:

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

Con suerte Apple le enseñará a 'cambiar' algunos trucos nuevos.

 114
Author: Graham Perks,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-10 14:55:41

Para mí, un buen camino fácil:

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;
}
 71
Author: sbonkosky,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-09-10 01:46:43

Desafortunadamente, las instrucciones switch solo se pueden usar en tipos primitivos. Sin embargo, tiene algunas opciones usando colecciones.

Probablemente la mejor opción sería almacenar cada valor como una entrada en 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]];
 9
Author: ughoavgfhw,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-11-17 03:34:18

Aquí está la forma más inteligente de escribir eso. Es usar un NSNumberFormatter en el estilo "deletrear":

NSString *cardName = ...;

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

Tenga en cuenta que el formateador de números quiere que la cadena esté en minúsculas, por lo que tenemos que hacerlo nosotros mismos antes de pasarla al formateador.

 6
Author: Dave DeLong,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-11-17 04:10:36

Hay otras maneras de hacer eso, pero switch no es una de ellas.

Si solo tiene unas pocas cadenas, como en su ejemplo, el código que tiene está bien. Si tiene muchos casos, puede almacenar las cadenas como claves en un diccionario y buscar el valor correspondiente:

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

NSNumber *value = [cases objectForKey:cardName];
if (value != nil) {
    [self setValue:[value intValue]];
}
 6
Author: Caleb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-21 21:58:47

Un poco tarde, pero para cualquier persona en el futuro pude hacer que esto funcionara para mí

#define CASE(str) if ([__s__ isEqualToString:(str)])
#define SWITCH(s) for (NSString *__s__ = (s); ; )
#define DEFAULT
 5
Author: Newyork167,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-14 20:00:06

Objective-c no es diferente de c en este aspecto, solo puede activar lo que c puede (y los def preproc como NSInteger, NSUInteger, ya que en última instancia son solo typedef'd a un tipo integral).

Wikipedia:

Sintaxis de C :

La instrucción switch hace que control se transfiera a una de varias instrucciones dependiendo del valor de una expresión, que debe tener el tipo integral.

Integral Tipos :

En ciencias de la computación, un entero es un dato de tipo de datos integral, a tipo de datos que representa algún subconjunto finito de la matemática entero. Los tipos de datos integrales pueden ser de diferentes tamaños y pueden no se permitirá que contengan valores negativos.

 3
Author: chown,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-11-17 03:35:38

DE LEJOS.. mi complemento "ObjC" FAVORITO es 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

Y también funciona con no cadenas... en bucles, incluso!

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.

Lo mejor de todo es que hay muy pocos {...} ' s, :'s, y ()'s

 3
Author: Alex Gray,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-25 15:56:00

Llego un poco tarde a la fiesta, pero para responder a la pregunta como se indica , hay una manera más inteligente:

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

Tenga en cuenta que indexOfObject buscará la coincidencia usando isEqual:, exactamente como en la pregunta.

 1
Author: ilya n.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-12-05 10:08:37

No puedo comentar la respuesta de cris en la respuesta de @Cris, pero me gustaría decir que:

Hay una LIMITACIÓN para el método de @cris:

Typedef enum no tomará valores alfanuméricos

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

} CardType;

Así que aquí hay otro:

Pila de enlaces sobre flujo Ir a este usuario responder "user1717750"

 0
Author: Puru,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:34:39

Basándose en la idea de @Graham Perks publicada anteriormente, diseñó una clase simple para hacer que el cambio de cadenas sea bastante simple y limpio.

@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

Lo usarías así:

[Switcher switchOnString:someString
                   using:@{
                               @"Spades":
                               ^{
                                   NSLog(@"Spades block");
                               },
                               @"Hearts":
                               ^{
                                   NSLog(@"Hearts block");
                               },
                               @"Clubs":
                               ^{
                                   NSLog(@"Clubs block");
                               },
                               @"Diamonds":
                               ^{
                                   NSLog(@"Diamonds block");
                               }
                           } withDefault:
                               ^{
                                   NSLog(@"Default block");
                               }
 ];

El bloque correcto se ejecutará de acuerdo con la cadena.

Síntesis de esta solución

 0
Author: Chuck Krutsinger,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-06 19:04:41
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;
    }
}

Disfrutar de la codificación.....

 -2
Author: Ek SAD.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-08 11:01:38