【问题标题】:Comparison of UIColorsUIColors的比较
【发布时间】:2026-02-22 20:30:02
【问题描述】:

我有一些代码我不知道为什么它不起作用,

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";
}

我还发现有些人重写了 isEqual 方法 isEqualtoColor: 但这也不起作用,我喂了一个 lastColor.CGColor;

我读到的所有地方都使用 isEqual 来比较 UIColors,我目前正在使用红色、绿色和蓝色的字符串数组,并将浮点值与 CGColorGetComponents(lastColor);

但这也不起作用。

【问题讨论】:

    标签: iphone uicolor


    【解决方案1】:

    gist.github.com/mtabini/716917

    上面的链接就像一个魅力。非常感谢“Count Chocula”巧克力的美味来源和 iPhone 答案:P

    我会点击回复您的帖子,但它很可能会误导任何想知道这里的人。

    一定只是一个浮动容差。

    【讨论】:

      【解决方案2】:

      这是已接受答案的 Swift 版本。我已经放弃了 CGColorSpaceRef 比较,因为我找不到直接的快速方法,但除了性能方面之外,它似乎不会影响结果。

      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
      }
      

      【讨论】:

        【解决方案3】:

        如果您从具有 RGB 颜色空间的 CGContext 中获取像素颜色,则它可能与 UIColor 类使用的颜色不匹配。 CGContext 中直接内存引用中的像素值将是 0-255(在 RGB 中)。根据您要比较的调色板,我可能会使用 uint8_t 值来避免浮动并根据 RGB 中的主要值执行广义比较

        【讨论】:

        • 不老实说,在火车上从这个网站 markj.net/iphone-uiimage-pixel-color> 得到它,所以如果我记得的话,它无法通过它 ATM 其相当低的水平。
        • 好的,链接不显示,但我很确定如果您从 UIImage 获取像素颜色,那么您正在读取移动到基于 RGB 颜色的上下文中的该图像的副本。 uint8_t 比较不​​会那么混乱,因为您避免了浮动比较问题
        【解决方案4】:

        您实际上是在初始化红色变量吗?这应该有效:

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

        【讨论】:

        • 是的,这是自定义的红色,而不是默认的 redColor,例如+ (UIColor *)colorWithRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha;我将这些值打印出来,它们都完全相同......完全一样......但是 isEqual 只是忽略了这个事实。
        • 这很奇怪。这对我有用: UIColor aColor = [UIColor colorWithRed:1.0 green:0.0 blue:0.0 alpha:1.0]; NSLog(@"%d", [aColor isEqual:[UIColor redColor]]);如果颜色具有完全相同的组件,则 -isEqual 应该可以正常工作。您检查了*所有组件,包括 alpha 吗?
        • 是的,但我不能与 redColor 相比,如果我按照你所说的 if([color isEqual: [UIColor red]]) 我得到一个 [*** Terminating app due to unaught exception 'NSInvalidArgumentException' , 原因: '+[UIColor redC]: unrecognized selector sent to class]
        • 这是从颜色中输出的 NLog,颜色 UIDeviceRGBColorSpace 0.968627 0.0941176 0 1,红色:UIDeviceRGBColorSpace 0.968627 0.0941176 0 1 .....就像我说的那样做 if([color isEqual: red] ) 只是不起作用。
        • 这真的很奇怪。您是否尝试过使用 Quartz 代替? if (CGColorEqualToColor([lastColor CGColor], [red CGColor])) { etc.
        【解决方案5】:

        -[UIColor isEqual:] 是比较颜色的内置方法。但是,您必须记住,虽然在特定设备上两种颜色在您看来可能相同,但它们在数学上可能不同,因此比较不平等。在您的眼睛看来不同的两种颜色(例如,RGB 中的“纯红色”与 CMYK 中的“纯红色”)在转换为中性颜色空间进行比较后,可能比较相等。

        色彩空间就是这样的 b__。 :)

        如果您告诉我们为什么要比较两种颜色,我们可能会为您提供比直接比较更好的解决方案。

        回应您的评论:不要将您的用户界面点击测试基于单个甚至多个像素的颜色。它们的绝对值会根据设备颜色空间而变化,从而导致误报和误报。相反,您可以通过在界面中放置不可见的UIButton 对象来定义“热点”区域,或者更好的是,通过使用更灵活的东西(例如CGPath)并测试触摸是否在其范围内。像下面这样的东西可能会起作用:

        @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
        

        【讨论】:

        • 我比较触摸时的像素颜色并将其传递给视图控制器,然后将显示适当的页面。