Issue with [UIColor getWhite:alpha:] - ios

I'm trying to use get the white value of a UIColor by the following (redColor is just for example):
UIColor *col = [UIColor redColor];
CGFloat *white;
if([col getWhite:white alpha:nil])
{
NSLog(#"worked");
}
else
{
NSLog(#"didn't");
}
But this always prints "didn't", and I don't understand why. UIColor.h's definition says "If the receiver is of a compatible color space, any non-NULL parameters are populated and 'YES' is returned. Otherwise, the parameters are left unchanged and 'NO' is returned." so I'm presuming that the receiver is of a non-compatible color space.... But I don't know what that means. Any ideas?

You are passing a pointer to a random piece of memory (CGFloat *white;)
You should create a static CGFloat and pass a reference to it
UIColor *col = [UIColor redColor];
CGFloat white;
if([col getWhite:&white alpha:nil])
{
NSLog(#"worked");
}
else
{
NSLog(#"didn't");
}
It is possible that it will not be able to convert from grayscale, you can check by trying
UIColor *col = [UIColor colorWithWhite:1.0 alpha:1.0];
CGFloat white;
if([col getWhite:&white alpha:nil])
{
NSLog(#"worked");
}
else
{
NSLog(#"didn't");
}

Related

Comparing equality of [UIColor colorWithPatternImage:]

I want to compare two UIColors that I generated using [UIColor colorWithPatternImage:] for equality. I can't seem to figure out how to do this.
[[UIColor colorWithPatternImage:[UIImage imageNamed:#"camo2"]] isEqual:
[UIColor colorWithPatternImage:[UIImage imageNamed:#"camo2"]]]
Always returns false, whether I use == or isEqual. Does anybody know if it's possible to properly compare colorWithPatternImages, or CGPatterns I suppose? I've also tried comparing CGColorGetPattern(color.CGColor) but that doesn't work either.
EDIT: The reason for this is I have a function that accepts a UIColor and gives me an NSString for displaying to the user.
+(NSString *)colorNameForColor:(UIColor *)color {
if ([color isEqual:[UIColor whiteColor]]) {
return #"White";
}
if ([color isEqual:[UIColor colorWithPatternImage:[UIImage imageNamed:#"camo"]]]) {
return #"Camo";
}
...
}
Is this just an insane thing to do? I suppose I could make my own object that has a color property and a colorName property...
Using Private APIs
This took some reverse engineering of CoreGraphics but I was able to find one private method _CGPatternGetImage which appears to return the image.
You'll need to include the following headers:
#include <dlfcn.h>
#import CoreGraphics;
Create a function pointer:
typedef CGImageRef (*CGPatternGetImage)(CGPatternRef pattern);
And then access the function:
-(void)comparePatterns
{
void *handle = dlopen("/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics", RTLD_NOW);
CGPatternGetImage getImage = (CGPatternGetImage) dlsym(handle, "CGPatternGetImage");
UIColor *aColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"pattern1"]];
UIColor *bColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"pattern1"]];
UIColor *cColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"pattern2"]];
NSData *aImageData = UIImagePNGRepresentation([UIImage imageWithCGImage:getImage(CGColorGetPattern(aColor.CGColor))]);
NSData *bImageData = UIImagePNGRepresentation([UIImage imageWithCGImage:getImage(CGColorGetPattern(bColor.CGColor))]);
NSData *cImageData = UIImagePNGRepresentation([UIImage imageWithCGImage:getImage(CGColorGetPattern(cColor.CGColor))]);
NSLog(#"Should be true: %d",[aImageData isEqual:bImageData]);
NSLog(#"Should be false: %d",[aImageData isEqual:cImageData]);
}
You probably don't want to access any private APIs in a production app but this might be useful for testing.
Using Associative References
If this is going on the App Store then a better solution could be creating a category for UIColor and give it an associative reference to store the pattern name or whatever is easiest for you to compare. This won't compare the actual images at all so it's possible that if you don't set the correct data to identify the pattern the comparison won't be accurate.
Include the header:
#import <objc/runtime.h>
Create the category:
#interface UIColor(CustomPatterns)
#property (strong, nonatomic) NSString* patternName;
#end
#implementation UIColor(CustomPatterns)
static char CUSTOM_PATTERNS_PATTERN_NAME_KEY;
#dynamic patternName;
-(void)setPatternName:(NSString *)patternName
{
objc_setAssociatedObject(self, &CUSTOM_PATTERNS_PATTERN_NAME_KEY, patternName, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
-(NSString *)patternName
{
return (NSString*)objc_getAssociatedObject(self, &CUSTOM_PATTERNS_PATTERN_NAME_KEY);
}
#end
And then you can set your custom data and compare:
-(void)comparePatterns
{
UIColor *aColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"1"]];
aColor.patternName = #"1";
UIColor *bColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"1"]];
bColor.patternName = #"1";
UIColor *cColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"2"]];
cColor.patternName = #"2";
NSLog(#"Should be true: %d",[aColor.patternName isEqualToString:bColor.patternName]);
NSLog(#"Should be false: %d",[aColor.patternName isEqualToString:cColor.patternName]);
}

Programatically change custom UiButton background color

Within my custom UIButton class called "ComingHomeButton", I'm not able to change the backgroundcolor
I would like to change it without creating images, but if it is the only way I will have to.
I also want to change the background color every time the button is tapped.
Here is what I have that doesnt work:
UIColor *color = [UIColor colorWithRed:1 green:1 blue:1 alpha:0.5];
[self setBackgroundColor:color];
self refers to my "ComingHomeButton"
Thank you so much :-)
You can create a counter, and then loop through colors when a button is tapped:
-(IBAction)buttonTapped:(id)sender {
if (!counter) {
counter = 0
}
if (counter%3 == 0) {
self.backgroundColor = [UIColor redColor]; //or whatever custom color you want to use
} else if (counter%3 == 1) {
self.backgroundColor = [UIColor blueColor];
} else if (counter%3 == 2) {
self.backgroundColor = [UIColor greenColor];
}
counter++
}
and you can add as many colors as you want to loop through. The % denotes the mod function, making sure that when counter is bigger than 2, it will still return a number between 0 and 2.
The number after the % is the number of colors to loop through.
UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(50, 50, 300, 100)];
btn.backgroundColor = [UIColor blueColor];
[self.view addSubview:btn];
The following code works fine for adding a button the a given view with a background button. Try using the dot notation instead of the message pass.
-(IBAction)buttonTapped:(id)sender {
sender.backgroundColor = [self randomColor];
}
-(UIColor *)randomColor
{
CGFloat red = arc4random() % 255 / 255.0;
CGFloat green= arc4random() % 255 / 255.0;
CGFloat blue= arc4random() % 255 / 255.0;
UIColor *color = [UIColor colorWithRed:red green:green blue:blue alpha:1.0];
return color;
}
I did not test the code I am not on my mac but it should work.

Sometimes category method return nil after UIImagePickerController

I use simple UIColor category for random color.
+ (UIColor *)randomColor {
return [UIColor colorWithRed:arc4random_uniform(255)/255.0
green:arc4random_uniform(255)/255.0
blue:arc4random_uniform(255)/255.0
alpha:1.0];
}
And I tested this code in viewDidAppear: method.
Method method = class_getClassMethod([UIColor class], #selector(randomColor));
NSLog(#"color=%#, method=%d", [UIColor randomColor], (method != NULL));
UIColor * color = [UIColor colorWithRed:arc4random_uniform(255)/255.0
green:arc4random_uniform(255)/255.0
blue:arc4random_uniform(255)/255.0
alpha:1.0];
NSLog(#"color=%#", color);
First time when viewC did appear, it works very well.
color=UIDeviceRGBColorSpace 0.0509804 0.0862745 0.160784 1, method=1
color=UIDeviceRGBColorSpace 0.784314 0.509804 0.964706 1
But after I present UIPickerImageController and cancel it,
it shows different result.
color=(null), method=1
color=UIDeviceRGBColorSpace 0.254902 0.576471 0.937255 1
Why this situation happen?
It is really weird. :(

Where should I store 30+ UIColors for quick reference?

I want to have 30+ constant UIColors so I can easily access them in my app. I'd like to be able to do something like this:
[self setBackgroundColor:[UIColor skyColor]];
[self setBackgroundColor:[UIColor dirtColor]];
[self setBackgroundColor:[UIColor yankeesColor]];
How can I do this?
Thanks!!
Define a category for UIColor:
In UIColor+MyColors.h:
#interface UIColor (MyColors)
+ (UIColor *)skyColor;
+ (UIColor *)dirtColor;
// and the rest of them
#end
In UIColor+MyColors.m:
#implementation UIColor (MyColors)
+ (UIColor *)skyColor {
static UIColor color = nil;
if (!color) {
// replace r, g, and b with the proper values
color = [UIColor colorWithRed:r green:g blue:b alpha:1];
}
return color;
}
+ (UIColor *)dirtColor {
static UIColor color = nil;
if (!color) {
// replace r, g, and b with the proper values
color = [UIColor colorWithRed:r green:g blue:b alpha:1];
}
return color;
}
// and the rest
#end
Edit:
As Martin R points out, a more modern approach to initializing the static color variable would be:
+ (UIColor *)skyColor {
static UIColor color = nil;
static dispatch_once_t predicate = 0;
dispatch_once(&predicate, ^{
// replace r, g, and b with the proper values
color = [UIColor colorWithRed:r green:g blue:b alpha:1];
});
return color;
}
This may actually be overkill in this case since there is no bad side-effect if two threads happen to initialize the nil static variable at the same time using the original code. But it is a better habit to use dispatch_once.
You can add lines like this:
#define kFirstColor [UIColor whiteColor]
#define kSecondColor [UIColor colorWithRed:100.0/255 green:100.0/255 blue:100.0/255 alpha:1.0]
At the beginning of a class or add a Color.h header to your project and import it when needed.
#import "Color.h"
Then you can use your custom colors this way:
self.view.backgroundColor = kSecondColor;

This objective C code does not change the color of label text

Debugger show some value in color . Please what am I doing wrong
#synthesize textLabel;
#synthesize textField;
#synthesize sliderRed;
#synthesize sliderGreen;
#synthesize sliderBlue;
- (void)dealloc
{
[textLabel release];
[super dealloc];
}
- (IBAction)updateLabel
{
NSString * textValue = [textField text];
float red = [sliderRed value]/255.f;
float green = [sliderGreen value]/255.f;
float blue = [sliderBlue value]/255.f;
UIColor *textColour = [[UIColor alloc]initWithRed:red green:green blue:blue alpha:1.0];
[textLabel setText:textValue];
[textLabel setTextColor:textColour];
}
I guess sliderRed, sliderGreen and sliderBlue are UISlider instances? What are their min/max values? If you left it at default 0.0 to 1.0 then this code would give you some really low values:
float red = [sliderRed value]/255.f;
float green = [sliderGreen value]/255.f;
float blue = [sliderBlue value]/255.f;
UIColor's method you use takes float parameters from 0.0 to 1.0 so simply passing it the slider values without dividing them would work.
And don't forget to put [textColour release]; at the end of that method or you will be leaking a new UIColor instance every time the method gets called.
Nothing wrong on your codes. maybe something wrong in other places.
Try to replace this line:
UIColor *textColour = [[UIColor alloc]initWithRed:red green:green blue:blue alpha:1.0];
to
UIColor *textColour = [UIColor redColor];
And check if the redColor works. if not, so it might something wrong in your other codes.
Try adding [textLabel setNeeedsDisplay] after you've changed the drawing attributes.

Resources