Search code examples
objective-cnsuserdefaultsnsdatauicolor

UIColor equality fails after storing it in NSUserDefaults


I am storing an UIColor in NSUserDefaults, and the problem that I am having is that a simple equality check fails (for my tests) when retrieving the color back. Can somebody explain why this fails?

UIColor *color = [UIColor colorWithRed: 0.922 green: 0.404 blue: 0.024 alpha: 1];
NSData *colorData = [NSKeyedArchiver archivedDataWithRootObject:color];

[[NSUserDefaults standardUserDefaults] setObject:colorData forKey:@"myColor"];

NSData *storedColorData = [[NSUserDefaults standardUserDefaults] objectForKey:@"myColor"];
UIColor *restoredColor = [NSKeyedUnarchiver unarchiveObjectWithData:storedColorData];

if ([color isEqual:restoredColor]) {
    NSLog(@"Same color");
} else {
    NSLog(@"Not the same color");
}

The result will be "Not the same color". Quick looking in the debugger will show that the colors are identical (the RGB and alpha values).


Solution

  • If you declare your UIColor like this:

    UIColor *color = [UIColor colorWithRed: (float)0.922 green: (float)0.404 blue: (float)0.024 alpha: (float)1];
    

    both ways to compare colors will return YES in your example:

    [color isEqual:restoredColor]
    CGColorEqualToColor(color.CGColor, restoredColor.CGColor)
    

    UPDATE: Category for comparison UIColor components

    @interface UIColor (Compare)
    
    - (BOOL)isEqualToColor:(UIColor *)otherColor;
    
    @end
    
    @implementation UIColor (Compare)
    
    - (BOOL)isEqualToColor:(UIColor *)otherColor {
        const CGFloat *components = CGColorGetComponents(self.CGColor);
        float colorOne[4] = {components[0], components[1], components[2], components[3]};
    
        const CGFloat *otherComponents = CGColorGetComponents(otherColor.CGColor);
        float colorTwo[4] = {otherComponents[0], otherComponents[1], otherComponents[2], otherComponents[3]};
    
        return colorOne[0] == colorTwo[0] && colorOne[1] == colorTwo[1] && colorOne[2] == colorTwo[2] && colorOne[3] == colorTwo[3];
    }
    
    @end