2

I have an array full of NSStrings and I need to use an NSString to change the color on an attributed text. I seperated the original NSString into an array containing the single NSString with the color but I am stuck here. The string from the array is [UIColor orangecolor]. I have tried this but it returns null.

 SEL blackSel = NSSelectorFromString(@"blackColor");
 UIColor* tColor = nil;
if ([UIColor respondsToSelector: blackSel])
  tColor  = [UIColor performSelector:blackSel];
user2076774
  • 405
  • 1
  • 8
  • 21
  • 1
    possible duplicate of [How to convert NSString to UIColor](http://stackoverflow.com/questions/8228339/how-to-convert-nsstring-to-uicolor) – Nitin Gohel Jun 15 '13 at 07:45
  • See my answer (http://stackoverflow.com/a/15456362/1704346) – Lithu T.V Jun 15 '13 at 08:18
  • possible duplicate of [Using a NSString to set a color for a label](http://stackoverflow.com/questions/15456299/using-a-nsstring-to-set-a-color-for-a-label) – Lithu T.V Jun 15 '13 at 08:22

5 Answers5

9

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
trojanfoe
  • 120,358
  • 21
  • 212
  • 242
4

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;
}
Lithu T.V
  • 19,955
  • 12
  • 56
  • 101
2

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];
I_Man
  • 41
  • 4
1

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))

Adam
  • 32,900
  • 16
  • 126
  • 153
0

[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.

Kiko Lobo
  • 547
  • 5
  • 13
  • This will also be free from someone inserting something bad in the selector to make a discrete call.. Meaning if you use NSSelectorFromString, and the source of the @"blackColor" is not controlled by you, someone could insert malicious code. – Kiko Lobo Jun 15 '13 at 20:09
  • I tried the above code but when I check the class of myConvertedColor I get null. The dictionary has values but its just when I try assigning to the UIColor instance I get null – user2076774 Jun 15 '13 at 23:16