如何比较UIColor?

131

我想检查UIImageView背景的颜色集。 我已经尝试过:

if(myimage.backgroundColor == [UIColor greenColor]){
...}
else{
...}

但是那样不起作用,即使我知道颜色是绿色,它总是进入else部分。

此外,是否有一种方法可以在调试控制台中输出当前颜色。

p [myimage backgroundColor]

po [myimage backgroundColor]

无法工作。

20个回答

1

我有一个类似的答案,更加简洁明了,易于阅读和使用:

extension UIColor {
   var rgba: (red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat) {
       var red = CGFloat.zero
       var green = CGFloat.zero
       var blue = CGFloat.zero
       var alpha = CGFloat.zero
    
       guard getRed(&red, green: &green, blue: &blue, alpha: &alpha) else {
           debugPrint("color could not be retrieved")
           return (1.0, 1.0, 1.0, 1.0)
       }
       return (red, green, blue, alpha)
   }

   static func == (lhs: UIColor, rhs: UIColor) -> Bool {
       return  lhs.rgba == rhs.rgba
   }
}

你可以像这样使用它:(来自boherna的引用)
UIColor.whiteColor == UIColor(hex: "#FFFFFF") // true
UIColor.black == UIColor(red: 0, green: 0, blue: 0, alpha: 1) // true

0

我已将Raf的回答转换为Swift 4(在CGColor API中有很多改变),去除了强制解包并减少了缩进,这要感谢对guard慷慨的使用:

@extension UIColor {
    func isEqualToColor(otherColor: UIColor) -> Bool {
        if self == otherColor {
            return true
        }
        let colorSpaceRGB = CGColorSpaceCreateDeviceRGB()
        let convertColorToRGBSpace: ((UIColor) -> UIColor?) = { (color) -> UIColor? in
            guard color.cgColor.colorSpace?.model == .monochrome else {
                return color
            }
            guard let oldComponents = color.cgColor.components else {
                return nil
            }
            let newComponents = [oldComponents[0], oldComponents[0], oldComponents[0], oldComponents[1]]
            guard let colorRef = CGColor(colorSpace: colorSpaceRGB, components: newComponents) else {
                    return nil
            }
            return UIColor(cgColor: colorRef)
        } 

        guard let selfColor = convertColorToRGBSpace(self), 
              let otherColor = convertColorToRGBSpace(otherColor) else {
            return false
        }
        return selfColor.isEqual(otherColor)
    }
}

0

UIColor扩展

- (CGFloat)accuracyCompareWith:(UIColor *)color {
    CIColor *c1 = [[CIColor alloc] initWithColor:self];
    CIColor *c2 = [[CIColor alloc] initWithColor:color];

    BOOL hasAlpha = c1.numberOfComponents == 4 && c2.numberOfComponents == 4;
    NSInteger numberOfComponents = hasAlpha ? 4 : 3;

    CGFloat colorMax = 1.0;
    CGFloat p = colorMax / 100.0;

    CGFloat redP = fabs(c1.red / p - c2.red / p);
    CGFloat greenP = fabs(c1.green / p - c2.green / p);
    CGFloat blueP = fabs(c1.blue / p - c2.blue / p);
    CGFloat alphaP = 0;

    if (hasAlpha)
        alphaP = fabs(c1.alpha / p - c2.alpha / p);

    return (redP + greenP + blueP + alphaP) / (CGFloat)numberOfComponents;
}

0

UIColor的扩展,使用Swift 2.2的特性。 需要注意的是,由于比较的是R G B A值,而这些值是CGFloat类型的,因此舍入误差可能会导致颜色不相等(例如,如果它们没有使用完全相同的属性在init(...)中创建,则不会被返回为相等)。

/**
 Extracts the RGBA values of the colors and check if the are the same.
 */

public func isEqualToColorRGBA(color : UIColor) -> Bool {
    //local type used for holding converted color values
    typealias colorType = (red : CGFloat, green : CGFloat, blue : CGFloat, alpha : CGFloat)
    var myColor         : colorType = (0,0,0,0)
    var otherColor      : colorType = (0,0,0,0)
    //getRed returns true if color could be converted so if one of them failed we assume that colors are not equal
    guard getRed(&myColor.red, green: &myColor.green, blue: &myColor.blue, alpha: &myColor.alpha) &&
        color.getRed(&otherColor.red, green: &otherColor.green, blue: &otherColor.blue, alpha: &otherColor.alpha)
        else {
            return false
    }
    log.debug("\(myColor) = \(otherColor)")
    //as of Swift 2.2 (Xcode 7.3.1), tuples up to arity 6 can be compared with == so this works nicely
    return myColor == otherColor
}

0

这里是一个在Swift中切换到RGC空间颜色的扩展:

extension UIColor {

func convertColorToRGBSpaceColor() -> UIColor {
    let colorSpaceRGB = CGColorSpaceCreateDeviceRGB()
    let oldComponents = CGColorGetComponents(self.CGColor)
    let components = [oldComponents[0], oldComponents[0], oldComponents[0], oldComponents[1]]
    let colorRef = CGColorCreate(colorSpaceRGB, components)
    let convertedColor = UIColor(CGColor: colorRef!)
    return convertedColor
}

}


0

虽然@samvermette的答案非常好,但我发现在比较不同颜色类型时(在我的情况下是UIDeviceRGBColorUICachedDeviceWhiteColor),有时会导致错误的负面结果。我通过在“else”中显式创建颜色来修复它:

- (BOOL)isEqualToColor:(UIColor *)otherColor
{
    if (self == otherColor)
        return YES;

    CGColorSpaceRef colorSpaceRGB = CGColorSpaceCreateDeviceRGB();

    UIColor *(^convertColorToRGBSpace)(UIColor*) = ^(UIColor *color)
    {
        if (CGColorSpaceGetModel(CGColorGetColorSpace(color.CGColor)) == kCGColorSpaceModelMonochrome)
        {
            const CGFloat *oldComponents = CGColorGetComponents(color.CGColor);
            CGFloat components[4] = {oldComponents[0], oldComponents[0], oldComponents[0], oldComponents[1]};
            CGColorRef colorRef = CGColorCreate(colorSpaceRGB, components);
            UIColor *color = [UIColor colorWithCGColor:colorRef];
            CGColorRelease(colorRef);
            return color;
        }
        else
        {
            const CGFloat *oldComponents = CGColorGetComponents(color.CGColor);
            CGFloat components[4] = {oldComponents[0], oldComponents[1], oldComponents[2], oldComponents[3]};
            CGColorRef colorRef = CGColorCreate(colorSpaceRGB, components);
            UIColor *color = [UIColor colorWithCGColor:colorRef];
            CGColorRelease(colorRef);
            return color;
        }
    };

    UIColor *selfColor = convertColorToRGBSpace(self);
    otherColor = convertColorToRGBSpace(otherColor);
    CGColorSpaceRelease(colorSpaceRGB);

    return [selfColor isEqual:otherColor];
}

0

这个怎么样:

+(BOOL)color:(UIColor *)color1 matchesColor:(UIColor *)color2
{
    CGFloat red1, red2, green1, green2, blue1, blue2, alpha1, alpha2;
    [color1 getRed:&red1 green:&green1 blue:&blue1 alpha:&alpha1];
    [color2 getRed:&red2 green:&green2 blue:&blue2 alpha:&alpha2];

    return (red1 == red2 && green1 == green2 && blue1 == blue2 && alpha1 == alpha2);
}

此代码可能无法处理边缘情况,如图案颜色。根据文档,如果颜色处于兼容的颜色空间内,则将颜色转换为RGB格式并将其组件返回给应用程序。如果颜色不在兼容的颜色空间内,则参数保持不变。因此,您可以使用“-1”实例化每个浮点数,如果调用“getRed:green:blue:alpha:”后仍然具有此值,则知道比较失败。(或者不要忽略返回的布尔值,因为它会告诉您是否成功调用。) - vikingosegundo
1
我刚刚检查了一下:虽然理论上可以将单色与RGBA颜色进行比较,但由于getRed:free:blue:alpha:在单色颜色上无法成功执行,因此您的代码无法产生另一个结果,只会得到“is equal:”(相等)。请参阅我的答案,了解如何处理此问题。 - vikingosegundo
以上代码适用于我的简单情况,但似乎并非万能解决方案。不错的东西。 - dooleyo

0
为什么不添加遵循可比协议的扩展呢? 这个答案使用了Nicolas Miari的解决方案。如果您喜欢这个答案,请点赞他的答案(排名第二)。
Zoul的评论:当使用这种方式比较颜色时要小心,因为它们必须在相同的颜色模型中才能被视为相等。例如,#ffffff并不等于[UIColor whiteColor]。
static func == (lhs: UIColor, rhs: UIColor) -> Bool {

    let colorSpaceRGB = CGColorSpaceCreateDeviceRGB()
    let convertColorToRGBSpace: ((UIColor) -> UIColor?) = { (color) -> UIColor? in
        guard color.cgColor.colorSpace?.model == .monochrome else {
            return color
        }
        guard let oldComponents = color.cgColor.components else {
            return nil
        }
        let newComponents = [oldComponents[0], oldComponents[0], oldComponents[0], oldComponents[1]]
        guard let colorRef = CGColor(colorSpace: colorSpaceRGB, components: newComponents) else {
            return nil
        }
        return UIColor(cgColor: colorRef)
    }

    guard let selfColor = convertColorToRGBSpace(lhs),
        let otherColor = convertColorToRGBSpace(rhs) else {
            return false
    }
    return selfColor.isEqual(otherColor)
}

0

你必须使用

BOOL equalColors = CGColorEqualToColor(uiColor1.CGColor, uiColor2.CGColor));

文档在这里


-1
if([myimage.backgroundColor isEqual:[UIColor greenColor]])

但它比这里的其他答案要好。 - return true

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接