9
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

UIColor の比較時の注意点

Last updated at Posted at 2016-06-01

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
9
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?