Objective C UIColor to NSString - objective-c

I need to convert a UIColor to an NSString with the name of the color i.e.
[UIColor redColor];
should become
#"RedColor"
I've already tried[UIColor redColor].CIColor.stringRepresentation
but it causes a compiler error

Just expanding on the answer that #Luke linked to which creates a CGColorRef to pass to CIColor:
CGColorRef colorRef = [UIColor grayColor].CGColor;
You could instead simply pass the CGColor property of the UIColor you're working on like:
NSString *colorString = [[CIColor colorWithCGColor:[[UIColor redColor] CGColor]] stringRepresentation];
Don't forget to import the Core Image framework.
Side note, a quick and easy way to convert back to a UIColor from the string could be something like this:
NSArray *parts = [colorString componentsSeparatedByString:#" "];
UIColor *colorFromString = [UIColor colorWithRed:[parts[0] floatValue] green:[parts[1] floatValue] blue:[parts[2] floatValue] alpha:[parts[3] floatValue]];

This is the shortest way to convert UIColor to NSString:
- (NSString *)stringFromColor:(UIColor *)color
{
const size_t totalComponents = CGColorGetNumberOfComponents(color.CGColor);
const CGFloat * components = CGColorGetComponents(color.CGColor);
return [NSString stringWithFormat:#"#%02X%02X%02X",
(int)(255 * components[MIN(0,totalComponents-2)]),
(int)(255 * components[MIN(1,totalComponents-2)]),
(int)(255 * components[MIN(2,totalComponents-2)])];
}

Related

Creating An Array of CGFloat for Gradient Locations

I'm trying to create a gradient color out of an array of dictionary (colorArray2). This dictionary contains 5 keys: r, g, b, a, p. r, g, b, a are component values (strings), p being the location. I'm trying to create a gradient color with initWithColors:atLocations:colorSpace. For now, I have the following.
NSGradient *aGradient;
NSColorSpace *space = [NSColorSpace genericRGBColorSpace];
NSMutableArray *cArray = [[NSMutableArray alloc] initWithObjects:nil]; // storing colors
NSMutableArray *pArray = [[NSMutableArray alloc] initWithObjects:nil]; // storing locations
for (NSInteger i2 = 0; i2 < colorArray2.count; i2++) {
NSString *r = [[colorArray2 objectAtIndex:i2] objectForKey:key2a];
NSString *g = [[colorArray2 objectAtIndex:i2] objectForKey:key2b];
NSString *b = [[colorArray2 objectAtIndex:i2] objectForKey:key2c];
NSString *a = [[colorArray2 objectAtIndex:i2] objectForKey:key2d];
NSString *p = [[colorArray2 objectAtIndex:i2] objectForKey:key2e];
NSColor *color = [NSColor colorWithSRGBRed:[r integerValue]/255.0f green:[g integerValue]/255.0f blue:[b integerValue]/255.0f alpha:[a integerValue]/100.0f];
[cArray addObject:color];
[pArray addObject:[NSNumber numberWithDouble:[p doubleValue]]];
}
So I have an array (cArray) containing colors. What I don't know is how to create an array of locations. According to the documentation, locations is an array of CGFloat values containing the location for each color in the gradient. How do I enumerate whatever to create a float array?
Thank you for your help.
Update
More specifically, how do I make pArray to get something like
double d[] = {0.1, 0.2, 0.3, 0.5, 1.0};
so that I can have
aGradient = [[NSGradient alloc] initWithColors:cArray atLocations:d colorSpace:space];
NSGradient's documentation states that locations parameter should be of type const CGFloat*, so you can't use NSArray*. The following should work:
// Allocate a C-array with the same length of colorArray2
CGFloat* pArray = (CGFloat*)malloc(colorArray2.count * sizeof(CGFloat));
for (NSInteger i2 = 0; i2 < colorArray2.count; i2++) {
// Extract location
NSString* p = [[colorArray2 objectAtIndex:i2] objectForKey:key2e];
pArray[i2] = [p doubleValue];
}
// Do whaterver with pArray
...
// Remember to free it
free(pArray);
You can use:
NSArray *colors = #[[NSColor colorWithWhite:.3 alpha:1.0],
[NSColor colorWithWhite:.6 alpha:1.0],
[NSColor colorWithWhite:.3 alpha:1.0]];
CGFloat locations[3] = {0.0, 0.5, 1.0};
NSGradient *gradient = [[NSGradient alloc] initWithColors:colors atLocations:locations colorSpace:[NSColorSpace genericRGBColorSpace]];
[gradient drawInRect:CGRectMake(100.0, 7.0, 10.0, 18.0) angle:-90];
To the other answers: no. Just no.
Actual answer:
How do I make an array of CGFloats in objective c?
First of all, this is Objective-C, not C. Technically you can use malloc, but that's a really terrible hack. You should convert to an NSNumber and then you can populate the NSArray. After, you can convert back using NSNumber's floatValue method. This way is proper Objective-C. Mixing and matching C and Obj-C just creates spaghetti code which is hard to read and eventually becomes unmaintainable.
I got it.
NSInteger count,index;
double *dArray;
count = pArray.count;
dArray = (double *) malloc(sizeof(double) * count);
for (index = 0; index < count; index++) {
dArray[index] = [[pArray objectAtIndex:index] floatValue];
}
aGradient = [[NSGradient alloc] initWithColors:cArray atLocations:dArray colorSpace:space];

Custom NSFormatter in Objective C

I am trying to write my own custom formatter in Objective C by subclassing NSNumberFormatter. Specifically what I'd like to do is make a number turn red if it is above or below certain values. The apple documentation says
For example, if you want negative financial amounts to appear in red, you have this method return a string with an attribute of red text. In attributedStringForObjectValue:withDefaultAttributes: get the non-attributed string by invoking stringForObjectValue: and then apply the proper attributes to that string.
Based on this advice I implemented the following code
- (NSAttributedString*) attributedStringForObjectValue: (id)anObject withDefaultAttributes: (NSDictionary*)attr;
{
NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] initWithString:[self stringForObjectValue:anObject]];
if ([[attrString string] floatValue] < -20.0f) {
[attrString addAttribute:#"NSForegroundColorAttributeName" value:[NSColor redColor] range:NSMakeRange(0, 10)];
return attrString;
} else return attrString;
}
But when I test this all it does is freeze my application. Any advice would be appreciated. Thanks.
I believe this has something to do with your NSRange that you create. I believe your length (10 in your example) is out of bounds. Try getting the length of the string that you use to initialize your NSMutableAttributedString.
For example:
- (NSAttributedString*) attributedStringForObjectValue: (id)anObject withDefaultAttributes: (NSDictionary*)attr;
{
NSString *string = [self stringForObjectValue:anObject];
NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] initWithString:string];
NSInteger stringLength = [string length];
if ([[attrString string] floatValue] < -20.0f)
{
[attrString addAttribute:#"NSForegroundColorAttributeName" value:[NSColor redColor] range:NSMakeRange(0, stringLength)];
}
return attrString;
}
Here is how I was finally able to implement this. To make it more visible when a number is negative, I decided to make the background of the text red with white text. The following code does work in a NSTextField cell. I'm not sure why the code in my question (and the answer) does not work, addAttribute should work.
- (NSAttributedString *)attributedStringForObjectValue:(id)anObject withDefaultAttributes: (NSDictionary *)attributes{
NSString *string = [self stringForObjectValue:anObject];
NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] initWithString:string];
NSInteger stringLength = [string length];
if ([[attrString string] floatValue] < 0)
{
NSDictionary *firstAttributes = #{NSForegroundColorAttributeName: [NSColor whiteColor],
NSBackgroundColorAttributeName: [NSColor blueColor]};
[attrString setAttributes:firstAttributes range:NSMakeRange(0, stringLength)];
}
return attrString;
}

Storing UIColors in NSDictionary and retrieving them?

I need to return a specific UIColor for a given index.
I am trying to basically store the UIColors as NSArrays
TypeColors = [[NSDictionary alloc] initWithObjectsAndKeys:
#"1", [NSArray arrayWithObjects:[NSNumber numberWithFloat:0.5],[NSNumber numberWithFloat:0.5],[NSNumber
numberWithFloat:0.5],[NSNumber numberWithFloat:1.0], nil],
#"5", [NSArray arrayWithObjects:[NSNumber numberWithFloat:1.0],[NSNumber
numberWithFloat:0.5],[NSNumber numberWithFloat:0.1],[NSNumber
numberWithFloat:1.0], nil]
, nil]; //nil to signify end of objects and keys.
And here I want to retrieve the UIColor back from that dictionary:
a = 5;
NSArray* colorArray = [TypeColors objectForKey:a];
UIColor* color = [UIColor colorWithRed:[colorArray objectAtIndex:0]
green:[colorArray objectAtIndex:1] blue:[colorArray objectAtIndex:2]
alpha:[colorArray objectAtIndex:3]];
It always returns me a zero, anyone knows why?
Thanks!
Change it to
UIColor* color = [UIColor colorWithRed:[[colorArray objectAtIndex:0] floatValue]
green:[[colorArray objectAtIndex:1] floatValue] blue:[[colorArray objectAtIndex:2] floatValue]
alpha:[[colorArray objectAtIndex:3] floatValue]];
The parameter to be sent there is cgfloat and not NSNumber
Two things:
1) The order of things in initWithObjectsAndKeys are objects and then their keys. Yes, it is intuitively backwards.
2) The key is not an integer 5 but an NSString #"5".
You need to convert your UIcolor to Nsstring first before save it in dictionary as follow :
-(NSString *)convertColorToString :(UIColor *)colorname
{
if(colorname==[UIColor whiteColor] )
{
colorname= [UIColor colorWithRed:1 green:1 blue:1 alpha:1];
}
else if(colorname==[UIColor blackColor])
{
colorname= [UIColor colorWithRed:0 green:0 blue:0 alpha:1];
}
else
{
colorname=colorname;
}
CGColorRef colorRef = colorname.CGColor;
NSString *colorString;
colorString=[CIColor colorWithCGColor:colorRef].stringRepresentation;
return colorString;
}
and when you want to fetch the value from dictionary than you need to convert string to color as follow
-(UIColor *)convertStringToColor :(NSDictionary *)dicname :(NSString *)keyname
{
CIColor *coreColor = [CIColor colorWithString:[dicname valueForKey:keyname]];
UIColor *color = [UIColor colorWithRed:coreColor.red green:coreColor.green blue:coreColor.blue alpha:coreColor.alpha];
//NSLog(#"color name :%#",color);
return color;
}
exa :
here dicSaveAllUIupdate is my dictionary and i saved my view background color in it.
[dicSaveAllUIupdate setObject:[self convertColorToString: self.view.backgroundColor] forKey:#"MAINVW_BGCOLOR"];
and i will retrive it as follow
self.view.backgroundColor=[self convertStringToColor:retrievedDictionary:#"MAINVW_BGCOLOR"];
Hope this help to you ...

How to set the UILabel's UIColor from a Plist

the question is in the title, How to set the UILabel's UIColor from a Plist ?
i tried this :
UIColor *colorLabel;
i add a NSString row in my Plist, and wrote redColor as a value but doesnt work...
How can i handle it ?
Thanks guys.
I would personally store the RGBA values instead of a string and then you can just use
+ (UIColor *)colorWithRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha
Do not do the below
Just as an interesting side note the most inflexible way would be to use the UIColor convenience methods like this
[UIColor performSelector:NSSelectorFromString(#"redColor")]
I think you need convert from string to an UIColor. You put colors into your plist by hex-colors (for red - ff0000) and then use something like following function for get UIColor.
+ (UIColor *) colorWithHexString: (NSString *) stringToConvert
{
    NSString *cString = [[stringToConvert stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] uppercaseString];
    // String should be 6 or 8 characters
    if ([cString length] < 6) return [UIColor blackColor];
    // strip 0X if it appears
    if ([cString hasPrefix:#"0X"]) cString = [cString substringFromIndex:2];
    if ([cString length] != 6) return [UIColor blackColor];
    // Separate into r, g, b substrings
    NSRange range;
    range.location = 0;
    range.length = 2;
    NSString *rString = [cString substringWithRange:range];
    range.location = 2;
    NSString *gString = [cString substringWithRange:range];
    range.location = 4;
    NSString *bString = [cString substringWithRange:range];
    // Scan values
    unsigned int r, g, b;
    [[NSScanner scannerWithString:rString] scanHexInt:&r];
    [[NSScanner scannerWithString:gString] scanHexInt:&g];
    [[NSScanner scannerWithString:bString] scanHexInt:&b];
    
    return [UIColor colorWithRed:((float) r / 255.0f)
                       green:((float) g / 255.0f)
                            blue:((float) b / 255.0f)
                       alpha:1.0f];
}
To preserve human readability, I did a category for this:
#implementation UIColor (EPPZRepresenter)
NSString *NSStringFromUIColor(UIColor *color)
{
const CGFloat *components = CGColorGetComponents(color.CGColor);
return [NSString stringWithFormat:#"[%f, %f, %f, %f]",
components[0],
components[1],
components[2],
components[3]];
}
UIColor *UIColorFromNSString(NSString *string)
{
NSString *componentsString = [[string stringByReplacingOccurrencesOfString:#"[" withString:#""] stringByReplacingOccurrencesOfString:#"]" withString:#""];
NSArray *components = [componentsString componentsSeparatedByString:#", "];
return [UIColor colorWithRed:[(NSString*)components[0] floatValue]
green:[(NSString*)components[1] floatValue]
blue:[(NSString*)components[2] floatValue]
alpha:[(NSString*)components[3] floatValue]];
}
#end
The same formatting that is used by NSStringFromCGAffineTransform. This is actually a part of a bigger scale plist object representer in eppz!kit at GitHub.

Store and get UIColor from .plist file

I've been searching for this for a while now with no success. My question is: is there an easy way to store and get UIColors such as [UIColor blackColor] or [UIColor colorWithRed:0.38 green:0.757 blue:1 alpha:1]; in a .plist file in my app directory?
according to this discussion you have two options:
Store it like NSData in Data field of .plist file
Store it like String UIColor representation
NSData option
NSData *theData = [NSKeyedArchiver archivedDataWithRootObject:[UIColor greenColor]];
NSString option
NSString *color = #"greenColor";
[UIColor performSelector:NSSelectorFromString(color)]
read more here: http://www.iphonedevsdk.com/forum/iphone-sdk-development/27335-setting-uicolor-plist.html
If you want to keep it human readabe,
I did a category for this:
#implementation UIColor (EPPZRepresenter)
NSString *NSStringFromUIColor(UIColor *color)
{
const CGFloat *components = CGColorGetComponents(color.CGColor);
return [NSString stringWithFormat:#"[%f, %f, %f, %f]",
components[0],
components[1],
components[2],
components[3]];
}
UIColor *UIColorFromNSString(NSString *string)
{
NSString *componentsString = [[string stringByReplacingOccurrencesOfString:#"[" withString:#""] stringByReplacingOccurrencesOfString:#"]" withString:#""];
NSArray *components = [componentsString componentsSeparatedByString:#", "];
return [UIColor colorWithRed:[(NSString*)components[0] floatValue]
green:[(NSString*)components[1] floatValue]
blue:[(NSString*)components[2] floatValue]
alpha:[(NSString*)components[3] floatValue]];
}
#end
The same formatting that is used by NSStringFromCGAffineTransform. This is actually a part of a bigger scale plist object representer in [eppz!kit at GitHub][1].
The best and readable way in Objective-c is to save it as hex string like: "#1A93A8", then to get it by extern method;
in .h file:
extern UIColor *colorFromHEX(NSString *hex);
extern NSString *HEXFromColor(UIColor *color);
in .m file:
UIColor *colorFromHEX(NSString *hex){
NSString *stringColor = hex;
int red, green, blue;
sscanf([stringColor UTF8String], "#%02X%02X%02X", &red, &green, &blue);
UIColor *color = [UIColor colorWithRed:red/255.0 green:green/255.0 blue:blue/255.0 alpha:1];
return color;
}
NSString *HEXFromColor(UIColor *color){
const CGFloat *components = CGColorGetComponents(color.CGColor);
size_t count = CGColorGetNumberOfComponents(color.CGColor);
if(count == 2){
return [NSString stringWithFormat:#"#%02lX%02lX%02lX",
lroundf(components[0] * 255.0),
lroundf(components[0] * 255.0),
lroundf(components[0] * 255.0)];
}else{
return [NSString stringWithFormat:#"#%02lX%02lX%02lX",
lroundf(components[0] * 255.0),
lroundf(components[1] * 255.0),
lroundf(components[2] * 255.0)];
}
}
in any where
NSDictionary *Config = [[NSDictionary alloc] initWithContentsOfFile:[NSBundle.mainBundle pathForResource:#"Config" ofType:#"plist"]];
UIColor *color = colorFromHEX( Config[#"color"] );
NSString *strColor = HEXFromColor( UIColor.blackColor );