Question

I have some code which I can't figure out why it's not working,

UIColor *lastColor, *red;
red = [UIColor colorWithRed:0.993 green:0.34444 blue:0.0 alpha:1.0]; 

NSString *chosenColor;

if([lastColor isEqual: red])
{
   chosenColor = @"red";
}

I have also found some people making an override of the isEqual method, isEqualtoColor: But this didn't work either and i fed that one lastColor.CGColor;

Everywhere I've read that isEqual is all you need to compare the UIColors, im currently resorting to an array of strings for red, green and blue and comparing the float value to the CGColorGetComponents(lastColor);

But this isn't working either.

Was it helpful?

Solution

gist.github.com/mtabini/716917

The link above works like a charm. Thanks awfully "Count Chocula" both a delicious source of chocolate and iphone answers :P

I'd click answered to your post but it would more then likly misslead any people wondering on here.

Must have just been a float tolerance.

OTHER TIPS

Here's a Swift version of the accepted answer. I've dropped the CGColorSpaceRef comparison as I couldn't find a straightforward way of doing that in swift, but it doesn't seem to impact the results other than in terms of performance.

class func colorsConsideredSimilar(color: UIColor, otherColor: UIColor) -> Bool {
    let tolerance: CGFloat = 0.05 // 5%

    let colorRef: CGColorRef = color.CGColor
    let otherColorRef: CGColorRef = otherColor.CGColor

    let componentCount = CGColorGetNumberOfComponents(colorRef)

    let components = CGColorGetComponents(colorRef)
    let otherComponents = CGColorGetComponents(otherColorRef)

    for var i = 0; i < componentCount; i++ {
        let difference = components[i] / otherComponents[i]

        if (fabs(difference - 1) > tolerance) {
            return false
        }
    }

    return true
}

If you are grabbing the pixel color from a CGContext with an RGB color space, then it may not match that used by the UIColor class. The pixel values in direct memory references into a CGContext are going to be 0-255 (in an RGB). Depending on the palette of colors you want to compare to, I would probably approach this using uint8_t values to avoid float and perform generalized comparisons based on the dominant values in RGB

Are you actually initializing the red variable? This should work:

if ([lastColor isEqual:[UIColor redColor]]) {
  /* … */
}

-[UIColor isEqual:] is the built-in way to compare colours. However, you must remember that while two colours may appear the same to your eyes on a particular device, they may differ mathematically and so compare unequal. Two colours that appear different to your eyes (for example, "pure red" in RGB vs. "pure red" in CMYK) may, upon conversion to a neutral colour space for comparison, compare equal.

Colour spaces are a b__ like that. :)

If you tell us why you want to compare two colours, we can possibly provide you with a better solution than direct comparison.

In response to your comment: Don't base your user interface hit testing on the colour of individual or even multiple pixels. Their absolute values can change based on the device colour space, leading to false positives and negatives. Rather, you can define "hotspot" regions by placing invisible UIButton objects in your interface, or better yet, by using something more flexible like CGPath and testing if a touch falls within its bounds. Something like the following might work:

@interface HotSpottyView : UIView {
    @private NSMutableDictionary *hotspots;
}
- (void)addHotspot: (CGPathRef)path withBlock: (void (^ handler)(void));
@end


@implementation HotSpottyView
- (id)initWithFrame: (CGRect)frameRect {
    self = [super initWithFrame: frameRect];

    if (self) {
        self->hotspots = [[NSMutableDictionary alloc] init];
    }

    return self;
}

- (id)initWithCoder: (NSCoder *)aDecoder {
    self = [super initWithFrame: frameRect];

    if (self) {
        self->hotspots = [[NSMutableDictionary alloc] init];
    }

    return self;
}

- (void)dealloc {
    [self->hotspots release];
    [super dealloc];
}

- (void)addHotspot: (CGPathRef)path withBlock: (void (^ handler)(void)) {
    CGPathRef immutablePath = CGPathCreateCopy(path);
    if (immutablePath) {
        [self->hotspots setObject: handler forKey: (id)immutablePath];
        CGPathRelease(immutablePath);
    }
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *t = [touches anyObject];
    CGPoint loc = [t locationInView: self];
    if (CGRectContainsPoint(self.bounds, loc)) {
        for (id path in self->hotspots) {
            if (CGPathContainsPoint((CGPathRef)path, NULL, loc, FALSE)) {
                void (^ handler)(void) = [self->hotspots objectForKey: path];
                handler();
            }
        }
    }
}
@end
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top