UIColor の比較
UIColor を比較する時に isEqual メソッド使用することができます。しかし、UIColor の whiteColor, blackColor で取得した UIColor を比較する時に問題が発生することがあります。
通常の場合
例えば次のように青色同士を比較する場合は問題ありません。
UIColor color = [UIColor colorWithRed:0.0f green:0.0f blue:1.0f alpha:1.0f];
UIColor* blueColor = [UIColor blueColor];
NSLog(@"Compare color to blue by isEqual: %@", [color isEqual:blueColor] ? @"YES" : @"NO");
実行結果
Compare color to blue by isEqual: YES
whiteColor の場合
しかし、whiteColor の場合上記のような方法だとうまくいきません。例えば次のようなコード
UIColor* color = [UIColor colorWithRed:1.0f green:1.0f blue:1.0f alpha:1.0f];
UIColor* white = [UIColor whiteColor];
CGFloat red, green, blue, alpha;
[color getRed:&red green:&green blue:&blue alpha:&alpha];
NSLog(@"color -> red:%lf, green:%lf, blue:%lf, alpha:%lf",red, green, blue, alpha);
[white getRed:&red green:&green blue:&blue alpha:&alpha];
NSLog(@"white -> red:%lf, green:%lf, blue:%lf, alpha:%lf",red, green, blue, alpha);
NSLog(@"color is %@", color.description);
NSLog(@"white is %@", white.description);
NSLog(@"Compare color to white by isEqual: %@, CGColorEqaulToColor: %@",
[color isEqual:white] ? @"YES" : @"NO",
CGColorEqualToColor(color.CGColor, white.CGColor) ? @"YES" : @"NO");
実行結果
color -> red:1.000000, green:1.000000, blue:1.000000, alpha:1.000000
white -> red:1.000000, green:1.000000, blue:1.000000, alpha:1.000000
color is UIDeviceRGBColorSpace 1 1 1 1
white is UIDeviceWhiteColorSpace 1 1
Compare color to white by isEqual: NO, CGColorEqaulToColor: NO
それぞれの RGBA の値は一緒ですが、isEqual や CGColorToColor の比較結果は NO になっています。
原因はカラースペース
それぞれの UIColor の description を見てもらうと RGBA を指定して作成したインスタンスは、UIDeviceRGBColorSpace になっているのに対して、whiteColor で取得した UIColor は UIDeviceWhiteColorSpace になっています。
このため、RGBA の値は一緒でもオブジェクトどうしの比較の際に NO となってしまうようです。
ちなみに HSB 値を指定して生成した場合は UIDeviceRGBColorSpace になるようです。
UIColor* color = [UIColor colorWithRed:1.0f green:1.0f blue:1.0f alpha:1.0f];
UIColor* hsb = [UIColor colorWithHue:0.0f saturation:0.0f brightness:1.0f alpha:1.0f];
CGFloat red, green, blue, alpha;
[color getRed:&red green:&green blue:&blue alpha:&alpha];
NSLog(@"color -> red:%lf, green:%lf, blue:%lf, alpha:%lf",red, green, blue, alpha);
[hsb getRed:&red green:&green blue:&blue alpha:&alpha];
NSLog(@"hsb -> red:%lf, green:%lf, blue:%lf, alpha:%lf",red, green, blue, alpha);
NSLog(@"color is %@", color.description);
NSLog(@"hsb is %@", hsb.description);
NSLog(@"Compare color to hsb by isEqual: %@, CGColorEqaulToColor: %@",
[color isEqual:hsb] ? @"YES" : @"NO",
CGColorEqualToColor(color.CGColor, hsb.CGColor) ? @"YES" : @"NO");
実行結果
color -> red:1.000000, green:1.000000, blue:1.000000, alpha:1.000000
hsb -> red:1.000000, green:1.000000, blue:1.000000, alpha:1.000000
color is UIDeviceRGBColorSpace 1 1 1 1
hsb is UIDeviceRGBColorSpace 1 1 1 1
Compare color to hsb by isEqual: YES, CGColorEqaulToColor: YES
解決方法
解決方法としては比較する時は RGBA 値を直接比較した方が安全なようです。
@interface UIColor (Compare)
- (BOOL)isEqualToColor:(UIColor*)color;
@end
@implementation UIColor (Compare)
- (BOOL)isEqualToColor:(UIColor *)color
{
CGFloat myRed, myGreen, myBlue, myAlpha;
[self getRed:&myRed green:&myGreen blue:&myBlue alpha:&myAlpha];
CGFloat otherRed, otherGreen, otherBlue, otherAlpha;
[color getRed:&otherRed green:&otherGreen blue:&otherBlue alpha:&otherAlpha];
return (myRed == otherRed && myGreen == otherGreen && myBlue == otherBlue && myAlpha == otherAlpha);
}
@end