the best way to implement readable switch case with strings in objective-c?

前端 未结 3 1311
野趣味
野趣味 2021-01-31 20:57

In other dynamic languages like ruby, javascript etc. you can do simply this:

switch(someString) {
    case \"foo\":
       //do something;
       break;
    cas         


        
相关标签:
3条回答
  • 2021-01-31 21:31
    typedef enum {
        foo,
        bar
    } FooBar;
    
    - (void) switchFooBar:(NSString *) param {
        switch([[cases objectForKey:param] intValue]) {
            case foo:
                NSLog(@"its foo");
                break;
            case bar:
                NSLog(@"its bar");
                break;
            default: 
                NSLog(@"its default");
                break;
        }
    }
    
    0 讨论(0)
  • 2021-01-31 21:35

    The technique is extracted from production code and modified to use colors for this example. The premise is that a string comes in with the text name of a color from some external feed. This inbound color name is matched against known Crayola color names in the system. If the new color name matches any known Crayola color name strings, the numeric value for HTML hex code equivalent of that Crayola color name is returned.

    First use http://www.unit-conversion.info/texttools/crc/ and put all of your known Crayola color names through it to get numerical equivalents. These will be used in the case statements. Then put those values into an enumerated for cleanliness (e.g. LivingColors below). These numbers become equivalent to the actual color name string.

    Then at run time the variable text is put through the same function, but internal to your code, to generate the same kind of numeric constant. If the numeric constant from the code matches the statically generated constant, then the text strings that they represent are exactly equal.

    The internal code function is crc32() found in zlib.h. This generates a unique number based upon the text put through it just like the web page converter above. The unique number from crc32() can then be used in a common C switch() statement to match against the known colors which were pre-processed into numbers into the enumerated.

    To use the native system function crc32() to generate CRC32B values, include the /usr/lib/libz.1.dylib in your project for linking. Be sure to include or #import <zlib.h> in your source that references crc32()

    Implement an Objective C category on NSString to make the native NSString class understand the crc32: and htmlColor: messages.

    Finally, read/get the name of the color into an NSString object, then send the string the htmlColor: message, it switches to match the 'strings' and returns the HTML hex equivalent value for a Crayola color name.

    #import <zlib.h>
    
    #define typedefEnum( enumName )               typedef enum enumName enumName; enum enumName
    
    /**
        @see Crayola Web Colors https://www.w3schools.com/colors/colors_crayola.asp
        @see CRC32B value generator for static case strings http://www.unit-conversion.info/texttools/crc/ or http://www.md5calc.com
    */
    
    #define typedefEnum( enumName ) typedef enum enumName enumName; enum enumName
    
    typedefEnum( LivingColors ) {
        kRedColor                   = 0xc22c196f,    // "Red" is 0xED0A3F in HTML
        kBlueberryColor             = 0xfbefa670,    // "Blueberry" is 0x4F86F7 in HTML
        kLightChromeGreenColor      = 0x44b77242,    // "Light Chrome Green" is 0xBEE64B in HTML
        kPermanentGeraniumLakeColor = 0xecc4f3e4,    // "Permanent Geranium Lake" is 0xE12C2C in HTML
        kIlluminatingEmeraldColor   = 0x4828d5f2,    // "Illuminating Emerald" is 0x319177 in HTML
        kWildWatermelonColor        = 0x1a17c629,    // "Wild Watermelon" is 0xFD5B78 in HTML
        kWashTheDogColor            = 0xea9fcbe6,    // "Wash the Dog" is 0xFED85D in HTML
        kNilColor                   = 0xDEADBEEF     // could use '0' but what fun is that?
    };
    
    
    // generates the CRC32B, same used to check each ethernet packet on the network you receive so it’s fast
    - (NSUInteger) crc32 {
        NSUInteger theResult;
    
        theResult = (NSUInteger)crc32(  0L,
                                        (const unsigned char *) [self UTF8String],
                                        (short)self.length);
    
        return theResult;
    }
    
    /// @return the HTML hex value for a recognized color name string.
    - (NSUInteger) htmlColor {
        NSUInteger      theResult               = 0x0;
        LivingColors    theColorInLivingColor   = kNilColor;
    
        theColorInLivingColor = (LivingColors) [self crc32];
         // return the HTML value for a known color by effectively switching on a string.
        switch ( theColorInLivingColor ) {
    
            case kRedColor : {
                theResult = 0xED0A3F;
            }
                break;
    
            case kBlueberryColor : {
                theResult = 0x4F86F7;
            }
                break;
    
            case kLightChromeGreenColor : {
                theResult = 0xBEE64B;
            }
                break;
    
            case kPermanentGeraniumLakeColor : {
                theResult = 0xE12C2C;
            }
                break;
    
            case kIlluminatingEmeraldColor : {
                theResult = 0x319177;
            }
                break;
    
            case kWildWatermelonColor : {
                theResult = 0xFD5B78;
            }
                break;
    
            case kWashTheDogColor : {
                theResult = 0xFED85D;
            }
                break;
    
            case kNilColor :
            default : {
                theResult = 0x0;
            }
                break;
    
        }
    
        return theResult;
    }
    

    For the example an Objective C Category was made to add the two methods the existing Cocoa class NSString, rather than subclass it.

    The end result is that an NSString object appears to have the ability to natively get a CRC32B value of itself (very handy beyond this example) and can essentially switch() on the color’s name string that possibly came in from the user, a text file, etc. to identify a match much faster than any text string comparison can occur.

    Fast, efficient, and reliable, this approach can easily be adapted to any kind of variable text matching to static known value text. Bear in mind that CRC32B checksums are generated by bitwise operations and the C switch statement use bitwise operations optimized at compile time. Remember this is speedy because CRC32B is the highly optimized function used to check each ethernet packet your Mac/iPhone/iPad receives... even when you download multi-gigabyte files like macOS Sierra.

    0 讨论(0)
  • 2021-01-31 21:43
    NSString * extension = [fileName pathExtension];
    NSString * directory = nil;
    
    NSUInteger index = [@[@"txt",@"png",@"caf",@"mp4"] indexOfObjectPassingTest:^
                        BOOL(id obj, NSUInteger idx, BOOL *stop)
    {
        return [obj isEqualToString:extension];
    }];
    
    switch (index)
    {
        case 0:
            directory = @"texts/";
            break;
        case 1:
            directory = @"images/";
            break;
        case 2:
            directory = @"sounds/";
            break;
        case 3:
            directory = @"videos/";
            break;
        default:
            @throw [NSException exceptionWithName:@"unkonwnFileFormat"
                                           reason:[NSString stringWithFormat:@"zip file contain nknown file format: %@",fileName]
                                         userInfo:nil];
            break;
    }
    
    0 讨论(0)
提交回复
热议问题