UIColor の比較時の注意点

# UIColor の比較

UIColor を比較する時に isEqual メソッド使用することができます。しかし、UIColor の whiteColor, blackColor で取得した UIColor を比較する時に問題が発生することがあります。

## 通常の場合

例えば次のように青色同士を比較する場合は問題ありません。

```objc
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");
```

**実行結果**
<pre>Compare color to blue by isEqual: YES</pre>

## whiteColor の場合
しかし、whiteColor の場合上記のような方法だとうまくいきません。例えば次のようなコード

```objc
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");
```

**実行結果**
<pre>
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
</pre>

　それぞれの RGBA の値は一緒ですが、isEqual や CGColorToColor の比較結果は　NO になっています。

## 原因はカラースペース
それぞれの UIColor の description を見てもらうと RGBA を指定して作成したインスタンスは、UIDeviceRGBColorSpace になっているのに対して、whiteColor で取得した UIColor は UIDeviceWhiteColorSpace になっています。
このため、RGBA の値は一緒でもオブジェクトどうしの比較の際に NO となってしまうようです。

ちなみに HSB　値を指定して生成した場合は UIDeviceRGBColorSpace になるようです。

```objc
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");
```

**実行結果**
<pre>
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
</pre>

## 解決方法
解決方法としては比較する時は RGBA 値を直接比較した方が安全なようです。

```objc
@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
```