2011-11-17 9 views
149

क्या इसे फिर से लिखने का एक और बुद्धिमान तरीका है?एनएसएसटींग पर उद्देश्य-सी स्विच कर सकते हैं?

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

नहीं, केवल पूर्णांक/bool/चार/आदि प्रकार पर काम करता है स्विच। – chown

+0

यह प्रश्न कुछ हद तक पहले ही पोस्ट किया गया है (http: // stackoverflow।कॉम/प्रश्न/816131 9/अत्यधिक-प्रदर्शन-उद्देश्य-सी-विकल्प-टू-द-स्विच-स्टेटमेंट-ऑब्जेक्ट्स) –

+2

ऐसा करने के कई वैकल्पिक तरीके हैं। उदाहरण के लिए, मानों के साथ एक सरणी लोड करें और सरणी में एक मैच की खोज करें। कोई भी बहुत कुशल नहीं है, लेकिन वे कोड डुप्लिकेशन को कम करते हैं। –

उत्तर

134

दुर्भाग्य से वे नहीं कर सकते हैं। स्विच स्विच स्टेटमेंट के उपयोग के बाद यह सबसे अच्छा और सबसे अधिक मांग है, इसलिए उम्मीद है कि वे (अब) जावा (और अन्य) बैंडवैगन पर आशा करते हैं!

यदि आप कार्ड नाम कर रहे हैं, तो शायद प्रत्येक कार्ड ऑब्जेक्ट को एक पूर्णांक मान असाइन करें और उस पर स्विच करें। या शायद एक enum, जिसे एक संख्या के रूप में माना जाता है और इसलिए इसे चालू किया जा सकता है।

उदा

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

} CardType; 

इस तरह से हो गया, ऐस मामले 1, आदि के रूप 0, दो केस के बराबर होना किया जाएगा

+31

whaaaaaaaat ?? वाह .. बस वाह .. – abbood

+2

यह एकमात्र तरीका है जो इसे किया जाना चाहिए। – Tristan

+4

@abbood enum के बारे में अधिक जानकारी के लिए, मैट थॉम्पसन द्वारा पोस्टिंग [NS_ENUM और NS_OPTIONS] (http://www.nshipster.com/ns_enum-ns_options/) देखें। –

6

वहाँ ऐसा करने के लिए अन्य तरीके हैं, लेकिन switch उनमें से एक नहीं है।

यदि आपके पास केवल कुछ स्ट्रिंग हैं, जैसा कि आपके उदाहरण में है, तो आपके पास कोड ठीक है। आप कई मामलों है, तो आप एक शब्दकोश में कुंजी के रूप में तार की दुकान और इसी मूल्य को दे सकता है:

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

NSNumber *value = [cases objectForKey:cardName]; 
if (value != nil) { 
    [self setValue:[value intValue]]; 
} 
9

दुर्भाग्य से, स्विच बयान केवल आदिम प्रकार पर इस्तेमाल किया जा सकता है। हालांकि, संग्रहों का उपयोग करके आपके पास कुछ विकल्प हैं।

शायद सबसे अच्छा विकल्प प्रत्येक मूल्य को 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]]; 
3

ऑब्जेक्टिव-सी सी इस पहलू में से अलग नहीं है, यह केवल (और preproc डीईएफ़ NSInteger, NSUInteger तरह के बाद से वे अंततः बस एक अभिन्न प्रकार के typedef'd कर रहे हैं) क्या ग कर सकते हैं पर स्विच कर सकते हैं ।

विकिपीडिया:

c syntax:

स्विच बयान का कारण बनता है एक अभिव्यक्ति है, जो अभिन्न प्रकार होना आवश्यक है के मूल्य के आधार कई बयानों में से एक को हस्तांतरित करने नियंत्रित करते हैं।

Integral Types:

कंप्यूटर विज्ञान में, एक पूर्णांक, अभिन्न डेटा प्रकार के एक गृहीत जो गणितीय पूर्णांक में से कुछ परिमित सबसेट का प्रतिनिधित्व करता है एक डेटा प्रकार है। इंटीग्रल डेटा प्रकार विभिन्न आकारों के हो सकते हैं और को नकारात्मक मान रखने की अनुमति नहीं दी जा सकती है।

6

यहां लिखने का अधिक बुद्धिमान तरीका है। यह "spell-out style" में एक NSNumberFormatter उपयोग करने के लिए है:

NSString *cardName = ...; 

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

ध्यान दें कि संख्या फ़ॉर्मेटर चाहता स्ट्रिंग लोवरकेस में रखना है, तो हम अपने आप को कि क्या करना है फ़ॉर्मेटर करने के लिए इसे पारित करने से पहले।

112

आप ब्लॉक के एक शब्दकोश सेट कर सकते हैं, इस तरह:

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 

एक 'डिफ़ॉल्ट' अनुभाग करवाने के लिए, के साथ अंतिम पंक्ति की जगह:

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

उम्मीद है कि एप्पल सिखा देगा 'स्विच 'कुछ नई चालें।

+29

मैं यह नहीं बता सकता कि यह वास्तव में बुरा या वास्तव में अच्छा है या नहीं। ऐसा करने के बारे में कभी सोचा नहीं होगा, धन्यवाद। – endy

+2

जबकि हम इस तरह की अजीब चीजें कर रहे हैं, तो अपनी खुद की कक्षा क्यों न बनाएं जो ब्लॉक ऑब्जेक्ट्स के लिए एनएसएसटींग कुंजियों से भरा एनएस डिक्शनरी लपेटती है और फिर डिफ़ॉल्ट मामलों के लिए एक और ब्लॉक प्रदान करती है? आप इसे सबस्क्रिप्ट नोटेशन का समर्थन भी कर सकते हैं। – ArtOfWarfare

+1

@endy मैं वास्तव में अच्छा वोट देता हूं। –

65

मेरे लिए, एक अच्छा आसान तरीका:

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

मुझे यह पसंद है। यह इस समस्या के उत्तर की तलाश में सबसे अधिक जरूरतों का उत्तर देता है, यह जावास्क्रिप्ट में एक समान स्विच की तुलना में अधिक टाइपिंग नहीं लेता है, और यह मानव पठनीय है। –

+4

मैं जेएस स्विच के साथ इस हैक की तुलना नहीं करूंगा। क्या होता है यदि अगला प्रोग्रामर आइटम 1 और आइटम 2 के बीच कोई आइटम जोड़ता है? बग्स पेश करने के लिए बहुत अधिक संभावना – Aras

+0

हालांकि यह एक अच्छा हैक है, इसलिए मैं आपको प्रयास के लिए अंगूठे देता हूं :) – Aras

0

मैं @Cris जवाब पर क्रिस के जवाब पर टिप्पणी नहीं कर सकता, लेकिन मैं यह कहना चाहते हैं:

@ क्रिस के लिए एक सीमा के भी नहीं है विधि:

typedef enum नहीं ले जाएगा अक्षरांकीय मान

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

} CardType; 
तो यहाँ

एक और पर है ई:

Link Stack over flow इस प्रयोक्ता जवाब "user1717750"

3

अब तक जाएं .. my FAVORITE "ObjC Add-On" is 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 

और यह गैर तार के साथ काम करता है, भी ... छोरों में, यहां तक ​​कि!

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. 

सबसे अच्छी बात यह है कि वहाँ बहुत कुछ {...} की, : के हैं, और () के

1

मैं एक तरह से देर से पार्टी के लिए, लेकिन जवाब सवाल में कहा गया है के रूप में करने के लिए

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

ध्यान दें कि indexOfObject वास्तव में सवाल में के रूप में मैच isEqual: प्रयोग करने के लिए दिखाई देगा,:, वहाँ एक और अधिक बुद्धिमान तरीका है।

3

थोड़ा देर से लेकिन भविष्य में किसी के लिए भी मैं इस के लिए काम करने के लिए प्राप्त करने में सक्षम था मुझे

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

यह दिलचस्प है। क्या आप और विस्तार कर सकते हैं? –

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

कोडिंग का आनंद लें .....

+0

लॉल, यह एक बड़ी असफल है, लेकिन मुझे प्रयास पसंद है – Loxx

0

@Graham सुविधाएं विचार पर बिल्डिंग पहले पोस्ट किया गया, तारों पर स्विचिंग को काफी सरल और साफ करने के लिए एक साधारण वर्ग तैयार किया गया।

@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 

आप इस तरह यह प्रयोग करेंगे:

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

सही ब्लॉक स्ट्रिंग के अनुसार निष्पादित करेंगे।

Gist for this solution

संबंधित मुद्दे