Convert NSString to UIColor

不打扰是莪最后的温柔 提交于 2019-12-06 10:42:35

I wrote a custom NSValueTransformer to allow me to translate NSColor to NSString (and back) for storage into NSUserDefaults as I didn't like the colours being stored using a byte array, which is the default behaviour. It also works across KVO, if you set the custom-transformer within IB. You can of course invoke the static methods in code to perform the transformation as well.

It shouldn't be a lot of work to rework this for UIColor:

StringColourTransformer.h:

#import <Cocoa/Cocoa.h>

@interface StringColourTransformer : NSValueTransformer

+ (NSString *)toString:(NSColor *)value;
+ (NSColor *)fromString:(NSString *)value;

@end

StringColourTransformer.m:

#import "StringColourTransformer.h"

@implementation StringColourTransformer

+ (NSString *)toString:(NSColor *)value
{
    StringColourTransformer *transformer = [[StringColourTransformer alloc] init];
    NSString *str = [transformer reverseTransformedValue:value];
    return str;
}

+ (NSColor *)fromString:(NSString *)value
{
    StringColourTransformer *transformer = [[StringColourTransformer alloc] init];
    NSColor *color = (NSColor *)[transformer transformedValue:value];
    return color;
}

+ (Class)transformedValueClass
{
    return [NSString class];
}

+ (BOOL)allowReverseTransformation
{
    return YES;
}

- (id)transformedValue:(id)value
{
    CGFloat r = 0.0, g = 0.0, b = 0.0, a = 1.0;

    // Only NSString classes are reverse-transformed
    if ([value isKindOfClass:[NSString class]])
    {
        NSString *stringValue = (NSString *)value;
        sscanf([stringValue UTF8String],
#ifdef __x86_64
               "%lf %lf %lf %lf",
#else
               "%f %f %f %f",
#endif
               &r, &g, &b, &a);
    }

    return [NSColor colorWithCalibratedRed:r green:g blue:b alpha:a];
}

- (id)reverseTransformedValue:(id)value
{
    CGFloat r = 0.0, g = 0.0, b = 0.0, a = 1.0;

    // Only NSColor classes are transformed
    if ([value isKindOfClass:[NSColor class]])
    {
        NSColor *colourValue = (NSColor *)value;
        NSColor *converted = [colourValue colorUsingColorSpaceName:@"NSCalibratedRGBColorSpace"];
        [converted getRed:&r green:&g blue:&b alpha:&a];
    }

    return [NSString stringWithFormat:@"%.3f %.3f %.3f %.3f", r, g, b, a];
}

@end

Use this method,Will convert colorname to the object UIColor

-(UIColor *)giveColorfromStringColor:(NSString *)colorname
{
    SEL labelColor = NSSelectorFromString(colorname);
    UIColor *color = [UIColor performSelector:labelColor];
    return color;
}

You could simply use for your strings this format @"1 0.96 0.75 1" in which the values are red, green, blue and alpha. then convert them to UIColor by using CIColor!

Here is a example:

      NSString *spinnerColorStr = @"1 0.96 0.75 1";
      CIColor *spinnerCi = [CIColor colorWithString:spinnerColorStr];
      UIColor *spinnerColor = [UIColor colorWithRed:spinnerCi.red green:spinnerCi.green blue:spinnerCi.blue alpha:spinnerCi.alpha];

Based on @trojanfoe's excellent answer, I made a category-based solution, which I'm using to dynamically configure UIViewControllers from their Info.plist file (helps when you have many apps sharing a common codebase):

UIColor+String.h:

#import <UIKit/UIKit.h>

@interface UIColor (String)

+(UIColor*) colorFromString:(NSString*) string;

@end

UIColor+String.m:

#import "UIColor+String.h"

@implementation UIColor (String)

/**
 c.f. http://stackoverflow.com/a/17121747/153422
 */
+(UIColor *)colorFromString:(NSString *)stringValue
{
    CGFloat r = 0.0, g = 0.0, b = 0.0, a = 1.0;
    sscanf([stringValue UTF8String],
#ifdef __x86_64
           "%lf %lf %lf %lf",
#else
           "%f %f %f %f",
#endif
           &r, &g, &b, &a);

    return [UIColor colorWithRed:r green:g blue:b alpha:a];
}

@end

Usage example:

NSString* colourString = [[NSBundle mainBundle].infoDictionary valueForKeyPath:@"Theme.Colours.NavigationBar.Title"];
    lTitle.textColor = [UIColor colorFromString:colourString];

(this assumes you edited your Info.plist and added a Dict "Theme" with a subdict "Colours", with a subdict "NavigationBar", with an NSString "Title" whose value is e.g. "1 0 0 1" (red))

[Look for edit below]

I would use a lookup table. In this case a dictionary that will hold the possible values as key's and the values as UIColor objects. Such as :

NSDictionary *colorTable = @{
    @"blackColor" : [UIColor blackColor],
    @"greenColor" : [UIColor greenColor],
    @"redColor" : [UIColor redColor]
};

So that way when you want to "convert" a color string, you would :

UIColor *myConvertedColor = [colorTable objectWithKey:@"blackColor"];

myConvertedColor will be a UIColorBlack.

Hope this helps! Good Luck!


--->>EDIT<<----

Ok, here's tested code. Try it somewhere clean so that you won't get interference from other things that might be running. Note that I am asuming iOS.. Otherwise change UIColor for NSColor..

  NSDictionary *colorTable = @{
                                 @"blackColor" : [UIColor blackColor],
                                 @"greenColor" : [UIColor greenColor],
                                 @"redColor" : [UIColor redColor]
                                 };


    UIColor *myConvertedColorNull = [colorTable objectForKey:@"whiteColor"]; //NULL
    UIColor *myConvertedColor = [colorTable objectForKey:@"blackColor"]; //NOT NULL

    NSLog(@"MyColor: %@", [myConvertedColor description]);
    NSLog(@"MyColorNULL: %@", [myConvertedColorNull description]);

This produces this output:

MyColor: UIDeviceWhiteColorSpace 0 1 MyColorNULL: (null)

As you can see, the MyColorNULL is to prove how you should not do the search, while the other proves that my code works.

if it helps, please tag my answer as correct. If it doesn't let's keep working it out.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!