53 votes

À l'aide d'un NSString dans une instruction switch

Est-il possible d'utiliser un NSString en switch déclaration?

Ou est-il préférable d'utiliser if / else if?

69voto

user1717750 Points 457

J'ai utiliser ces macros dans mon application.

#define CASE(str)                       if ([__s__ isEqualToString:(str)]) 
#define SWITCH(s)                       for (NSString *__s__ = (s); ; )
#define DEFAULT   

SWITCH (string) {
    CASE (@"AAA") {
        break;
    }
    CASE (@"BBB") {
        break;
    }
    CASE (@"CCC") {
        break;
    }
    DEFAULT {
        break;
    }
 }

53voto

Vladimir Points 110327

commutateur de déclaration de constantes entières pour ce type de cas, pour NSString ne peut pas être utilisé ici, il semble donc que vous devez aller pour si/d'autre option.

Un autre point est que vous devez comparer NSStrings à l'aide de isEqualToString: ou comparer: la méthode, de sorte que même si le pointeur de valeurs ont été autorisés pour la mise en marche des cas, vous ne pourriez pas utiliser de toute façon

12voto

alex gray Points 5089

En réponse et en soutien de @Cœur de la réponse.. Ici c'est la même chose, mais écrit dans Xcode 4.4 / Clang / Whatever "la syntaxe littérale" qui est encore plus proche d'un simple urnary if, else de la comparaison (et c'est le point, n'est-il pas.....)

NSDictionary *action = @{ @"A" : ^{ NSLog (@"Perform Block A here!"); },
                          @"B" : ^{ NSLog (@"Perform Block B here!"); } };

((void (^)()) [action objectForKey:stringToTest] )();

ou dire, vous souhaitez effectuer un sélecteur de fonction sur le titre d'un bouton...

- (IBAction) multiButtonTarget:(id)btn {     ((void (^)()) [
 @{ @"Click!" : ^{ self.click; }, 
    @"Exit!"  : ^{   exit(-1); } objectForKey:((NSButton*)sender).title] )();
}

Bref, comme w.string = kIvar == 0 ? @"StringA" : @"StringB";, et d'autant plus utile, que vous pouvez pousser les blocs de là, sans même une pensée de certains terrible (et limité, et alambiqué) @selector!

EDIT: C'est plus évidemment construit en tant que tel:

[@[ @"YES", @"NO", @"SIRPOOPSALOT"] do:^(id maybe) {
    [maybe isEqual:@"YES"] ? ^{ NSLog(@"You got it!"); }()
  : [maybe isEqual:@"NO" ] ? ^{ NSLog(@"You lose!!!"); }() 
  :                          ^{ NSLog(@"Not sure!"); [self tryAgain]; }();
}]; 

*** You got it! ****** You lose!!! ****** Not sure! ***

Je dois avouer que je suis plutôt embarrassant DANS ce type syntaxique de la bêtise. Une autre option est d'oublier ce que la chaîne est.. juste l'exécuter, lol...

[ @{ NSApplicationWillBecomeActiveNotification : @"slideIn",
     NSApplicationDidResignActiveNotification  : @"slideOut" } each:^( id key, id obj ) {
    [w observeObject:NSApp forName:obj calling: NSSelectorFromString ( obj ) ];       
}];

ou la prise de l'INTERFACE utilisateur de la parole, littéralement..

- (IBAction)setSomethingLiterallyWithSegmentedLabel:(id)sender {
   NSInteger selectedSegment = [sender selectedSegment];
   BOOL isSelected = [sender isSelectedForSegment:selectedSegment];
   BOOL *optionPtr = &isSelected;
   SEL fabricated = NSSelectorFromString
       ([NSString stringWithFormat:@"set%@:",[sender labelForSegment:selectedSegment]]);
   [self performSelector:fabricated withValue:optionPtr];
}

10voto

Cœur Points 1538

Instruction Switch ne fonctionne pas avec NSString: il fonctionne uniquement avec des int.

If/Else est trop de code et ne sont souvent pas optimale.

La solution optimale est d'utiliser un NSDictionary indexés par le NSString (ou autres objets) possibilités. Ensuite, vous accédez directement sur la droite de la valeur de la fonction/.

Exemple 1, lorsque vous voulez tester @"A" ou"B" et d'effectuer methodA ou methodB:

NSDictionary *action = @{@"A" : [NSValue valueWithPointer:@selector(methodA)],
                         @"B" : [NSValue valueWithPointer:@selector(methodB)],
                         };
[self performSelector:[action[stringToTest] pointerValue]];

Exemple 2, si vous voulez tester par @"A" ou"B" et d'effectuer blockA ou blockB:

NSDictionary *action = @{@"A" : ^{ NSLog (@"Block A"); },
                         @"B" : ^{ NSLog (@"Block B"); },
                         };
((void (^)())action[stringToTest])();

1voto

vikingosegundo Points 30323

inspiré par alex gray, j'ai créé une catégorie de méthode, qui s'applique enchaîné les filtres à son objet:

.h

#import <Foundation/Foundation.h>
typedef id(^FilterBlock)(id element,NSUInteger idx, BOOL *stop);

@interface NSObject (Functional)
-(id)processByPerformingFilterBlocks:(NSArray *)filterBlocks;
@end

.m

#import "NSObject+Functional.h"

@implementation NSObject (Functional)
-(id)processByPerformingFilterBlocks:(NSArray *)filterBlocks
{
    __block id blockSelf = self;
    [filterBlocks enumerateObjectsUsingBlock:^( id (^block)(id,NSUInteger idx, BOOL*) , NSUInteger idx, BOOL *stop) {
        blockSelf = block(blockSelf, idx, stop);
    }];

    return blockSelf;
}
@end

Vous pouvez l'utiliser comme

FilterBlock fb1 = ^id(id element, NSUInteger idx, BOOL *stop){ if ([element isEqualToString:@"YES"]) { NSLog(@"You did it");  *stop = YES;} return element;};
FilterBlock fb2 = ^id(id element, NSUInteger idx, BOOL *stop){ if ([element isEqualToString:@"NO"] ) { NSLog(@"Nope");        *stop = YES;} return element;};

NSArray *filter = @[ fb1, fb2 ];
NSArray *inputArray = @[@"NO",@"YES"];

[inputArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
    [obj processByPerformingFilterBlocks:filter];
}];

mais vous pouvez aussi faire plus de trucs compliqués, comme appliqués chianed calculs:

FilterBlock b1 = ^id(id element,NSUInteger idx, BOOL *stop) {return [NSNumber numberWithInteger:[(NSNumber *)element integerValue] *2 ];};
FilterBlock b2 = ^id(NSNumber* element,NSUInteger idx, BOOL *stop) {
    *stop = YES;
    return [NSNumber numberWithInteger:[element integerValue]*[element integerValue]];
};
FilterBlock b3 = ^id(NSNumber* element, NSUInteger idx,BOOL *stop) {return [NSNumber numberWithInteger:[element integerValue]*[element integerValue]];};

NSArray *filterBlocks = @[b1,b2, b3, b3, b3];
NSNumber *numberTwo = [NSNumber numberWithInteger:2];
NSNumber *numberTwoResult = [numberTwo processByPerformingFilterBlocks:filterBlocks];    
NSLog(@"%@ %@", numberTwo, numberTwoResult);

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