Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/102.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 如何比较颜色?_Ios_Objective C_Cocoa Touch_Uiimageview_Uicolor - Fatal编程技术网

Ios 如何比较颜色?

Ios 如何比较颜色?,ios,objective-c,cocoa-touch,uiimageview,uicolor,Ios,Objective C,Cocoa Touch,Uiimageview,Uicolor,我想检查UIImageView背景的颜色设置。我试过: if(myimage.backgroundColor == [UIColor greenColor]){ ...} else{ ...} 但这不起作用,即使我知道颜色是绿色,它总是落在其他部分 另外,是否有方法在调试控制台中输出当前颜色 p [myimage backgroundColor] 及 不起作用。你试过[myColor isEqual:someOtherColor]吗?正如zoul在评论中指出的那样,isEqual:在比较不同

我想检查UIImageView背景的颜色设置。我试过:

if(myimage.backgroundColor == [UIColor greenColor]){
...}
else{
...}
但这不起作用,即使我知道颜色是绿色,它总是落在其他部分

另外,是否有方法在调试控制台中输出当前颜色

p [myimage backgroundColor]


不起作用。

你试过
[myColor isEqual:someOtherColor]
吗?

正如zoul在评论中指出的那样,
isEqual:
在比较不同型号/空间中的颜色时(例如
\FFF
[UIColor whiteColor]
)将返回
。我编写了这个UIColor扩展,它在比较两种颜色之前将两种颜色转换为相同的颜色空间:

if([myimage.backgroundColor isEqual:[UIColor greenColor]])
- (BOOL)isEqualToColor:(UIColor *)otherColor {
    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
            return color;
    };

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

    return [selfColor isEqual:otherColor];
}
#导入“UIColor Expanded.h”
//https://github.com/thetaplab/uicolor-utilities
//RGB距离
CGFloat距离=sqrtf(功率((clr0.red-clr1.red),2)+功率((clr0.green-clr1.green),2)+功率((clr0.blue-clr1.blue),2));
如果(距离)
当您像这样比较
myimage.backgroundColor==[UIColor greenColor]
时,如果您在该语句之前没有将backgroundColor更改为绿色,则它不起作用

我在我的颜色游戏中也遇到了同样的问题,我解决了这个问题,通过在RGB颜色中使用简单的差分方程,您可以快速查看短代码示例颜色过程

这就像胜利者的回答

GFloat distance = sqrtf(powf((clr0.red - clr1.red), 2) + powf((clr0.green - clr1.green), 2) + powf((clr0.blue - clr1.blue), 2) );
if(distance<=minDistance){
....
}else{
…
}
当然,如果它返回0,则表示您比较的颜色太相似。返回范围类似于(0.0f-1.5f)

那么:

+(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);
}

我编写了这个类别。如果
isEqual:
返回否,它将测试不同组件的进一步比较是否仍然匹配。如果可能,不同的模型仍然会进行比较

@implementation UIColor (Matching)


-(BOOL)matchesColor:(UIColor *)color error:(NSError *__autoreleasing *)error
{
    UIColor *lhs = self;
    UIColor *rhs = color;

    if([lhs isEqual:rhs]){ // color model and values are the same
        return YES;
    }

    CGFloat red1, red2, green1, alpha1, green2, blue1, blue2, alpha2;
    BOOL lhsSuccess = [lhs getRed:&red1 green:&green1 blue:&blue1 alpha:&alpha1];
    BOOL rhsSuccess = [rhs getRed:&red2 green:&green2 blue:&blue2 alpha:&alpha2];
    if((!lhsSuccess && rhsSuccess) || (lhsSuccess && !rhsSuccess)){ // one is RGBA, one color not.
        CGFloat r,g,b,a;
        if(!lhsSuccess){ // lhs color could be a monochrome
            const CGFloat *components = CGColorGetComponents(lhs.CGColor);
            if([lhs _colorSpaceModel] == kCGColorSpaceModelMonochrome){
                r = g = b = components[0];
                a = components[1];

                return r == red2 && g == green2 && b == blue2 && a == alpha2;
            }
        } else {  // rhs color could be a monochrome
            const CGFloat *components = CGColorGetComponents(rhs.CGColor);

            if([rhs _colorSpaceModel] == kCGColorSpaceModelMonochrome){
                r = g = b = components[0];
                a = components[1];
                return r == red1 && g == green1 && b == blue1 && a == alpha1;
            }
        }


        NSError *aError = [[NSError alloc] initWithDomain:@"UIColorComparision" code:-11111 userInfo:[self _colorComparisionErrorUserInfo]];
        *error = aError;
        return  NO;
    } else if (!lhsSuccess && !rhsSuccess){ // both not RGBA, lets try HSBA
        CGFloat hue1,saturation1,brightness1;
        CGFloat hue2,saturation2,brightness2;

        lhsSuccess = [lhs getHue:&hue1 saturation:&saturation1 brightness:&brightness1 alpha:&alpha1];
        rhsSuccess = [lhs getHue:&hue2 saturation:&saturation2 brightness:&brightness2 alpha:&alpha2];
        if((!lhsSuccess && rhsSuccess) || (lhsSuccess && !rhsSuccess)){
            NSError *aError = [[NSError alloc] initWithDomain:@"UIColorComparision" code:-11111 userInfo:[self _colorComparisionErrorUserInfo]];
            *error = aError;
            return  NO;
        } else if(!lhsSuccess && !rhsSuccess){ // both not HSBA, lets try monochrome
            CGFloat white1, white2;

            lhsSuccess = [lhs getWhite:&white1 alpha:&alpha1];
            rhsSuccess = [rhs getWhite:&white2 alpha:&alpha2];
            if((!lhsSuccess && rhsSuccess) || (lhsSuccess && !rhsSuccess)){
                NSError *aError = [[NSError alloc] initWithDomain:@"UIColorComparision" code:-11111 userInfo:[self _colorComparisionErrorUserInfo]];
                *error = aError;
                return  NO;
            } else {
                return white1 == white2 && alpha1 == alpha2;
            }

        } else {
            return hue1 == hue2 && saturation1 == saturation2 && brightness1 == brightness2 && alpha1 == alpha2;
        }

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

    }
}

-(NSDictionary *)_colorComparisionErrorUserInfo{

    NSDictionary *userInfo = @{
                               NSLocalizedDescriptionKey: NSLocalizedString(@"Comparision failed.", nil),
                               NSLocalizedFailureReasonErrorKey: NSLocalizedString(@"The colors models are incompatible. Or the color is a pattern.", nil),

                               };
    return userInfo;
}

- (CGColorSpaceModel)_colorSpaceModel {
    return CGColorSpaceGetModel(CGColorGetColorSpace(self.CGColor));
}

@end


这可能有点晚了,但CoreGraphics有一个更容易实现的API:

CGColorEqualToColor(myColor.CGColor, [UIColor clearColor].CGColor)
正如文件所说:

指示两种颜色是否相等。 如果两种颜色具有相等的颜色空间和数值相等的颜色分量,则它们是相等的


这解决了许多问题和泄漏/自定义算法。

samvermette的解决方案转化为swift:

extension UIColor {
    func isEqualToColor(otherColor : UIColor) -> Bool {
        if self == otherColor {
            return true
        }

        let colorSpaceRGB = CGColorSpaceCreateDeviceRGB()
        let convertColorToRGBSpace : ((color : UIColor) -> UIColor?) = { (color) -> UIColor? in
            if CGColorSpaceGetModel(CGColorGetColorSpace(color.CGColor)) == CGColorSpaceModel.Monochrome {
                let oldComponents = CGColorGetComponents(color.CGColor)
                let components : [CGFloat] = [ oldComponents[0], oldComponents[0], oldComponents[0], oldComponents[1] ]
                let colorRef = CGColorCreate(colorSpaceRGB, components)
                let colorOut = UIColor(CGColor: colorRef!)
                return colorOut
            }
            else {
                return color;
            }
        }

        let selfColor = convertColorToRGBSpace(color: self)
        let otherColor = convertColorToRGBSpace(color: otherColor)

        if let selfColor = selfColor, otherColor = otherColor {
            return selfColor.isEqual(otherColor)
        }
        else {
            return false
        }
    }
}

可能会出现一些奇怪的舍入错误。这可能是对象设置为颜色和您设置为颜色不完全匹配的原因

我就是这样解决的:

private func compareColors (c1:UIColor, c2:UIColor) -> Bool{
    // some kind of weird rounding made the colors unequal so had to compare like this

    var red:CGFloat = 0
    var green:CGFloat  = 0
    var blue:CGFloat = 0
    var alpha:CGFloat  = 0
    c1.getRed(&red, green: &green, blue: &blue, alpha: &alpha)

    var red2:CGFloat = 0
    var green2:CGFloat  = 0
    var blue2:CGFloat = 0
    var alpha2:CGFloat  = 0
    c2.getRed(&red2, green: &green2, blue: &blue2, alpha: &alpha2)

    return (Int(green*255) == Int(green2*255))

}

此代码不仅可以通过比较1来改进,还可以通过比较所有组件来改进。例如,红色+绿色+蓝色+阿尔法==红色2+绿色2+蓝色2+阿尔法2

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
}

}

我正在使用这个扩展,它在任何情况下都适用于我

/***** UIColor Extension to Compare colors as string *****/
@interface UIColor (compare)
- (BOOL)compareWithColor:(UIColor *)color;
@end

@implementation UIColor(compare)
- (BOOL)compareWithColor:(UIColor *)color {
    return ([[[CIColor colorWithCGColor:self.CGColor] stringRepresentation] isEqualToString:[[CIColor colorWithCGColor:color.CGColor] stringRepresentation]]);
}
@end
/**** End ****/
希望帮助一些人


注意:
#ffffff
通过此扩展

使用Swift 2.2功能对UIColor进行扩展,等于
[UIColor whiteColor]
- (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;
}
但是请注意,由于比较了R G B A值,并且这些值是CGFloat,如果颜色不完全相同(例如,它们最初不是使用init(…)!)中完全相同的属性创建的),则舍入错误可能会导致颜色不返回相等

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

如果比较的颜色可以转换为RGB格式(大多数情况下应该是RGB格式),则此UIColor扩展可以正常工作

public extension UIColor {

    static func == (l: UIColor, r: UIColor) -> Bool {
        var l_red = CGFloat(0); var l_green = CGFloat(0); var l_blue = CGFloat(0); var l_alpha = CGFloat(0)
        guard l.getRed(&l_red, green: &l_green, blue: &l_blue, alpha: &l_alpha) else { return false }
        var r_red = CGFloat(0); var r_green = CGFloat(0); var r_blue = CGFloat(0); var r_alpha = CGFloat(0)
        guard r.getRed(&r_red, green: &r_green, blue: &r_blue, alpha: &r_alpha) else { return false }
        return l_red == r_red && l_green == r_green && l_blue == r_blue && l_alpha == r_alpha
    }
}
至少通过此扩展:

UIColor.whiteColor == UIColor(hex: "#FFFFFF") // true
UIColor.black == UIColor(red: 0, green: 0, blue: 0, alpha: 1) // true
如果使用本机UColor进行比较,两种比较结果都将返回false。isEqual(…)

我已转换为Swift 4(CGColor
API中的许多更改),由于大量使用
防护装置,消除了强制展开并减少了缩进:

@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)
    }
}

为什么不使用equalable协议添加扩展? 这个答案使用的是尼古拉斯·米阿里的解决方案。因此,如果你喜欢这个答案,欢迎你喜欢他的答案(倒数第二)

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)
}

虽然@samvermette的答案很好,但我发现在比较不同的颜色类型时(在我的例子中,
UIDeviceRGBColor
UICachedDeviceWhiteColor
),它有时会导致误判。我也通过在“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];
}
你必须使用

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

文档。

我阅读并尝试了本页的所有答案,我认为这是最好的,我对其进行了润色,结果如下:

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
}
}
你可以这样使用它:(引用bohera的话)


谢谢。isEqualTo有什么区别?另外,你知道如何在调试器中显示它吗?顺便说一下:用这种方式比较颜色时要小心,因为它们必须在相同的颜色模型中才能被视为相等。例如,#
ffffff
不等于
[UIColor whiteColor]
.Good point Zoul,指向解决方案可能更有用,而不仅仅是问题Through=DGood point Pfrank,指向解决方案可能更有用,而不仅仅是问题Through=DDid在比较button.tintColor与我设置的颜色时并不总是对我有效。与舍入有关。如果遇到此问题,请参阅下面的答案。很好,但是我认为有一个漏洞。你从来没有在中间释放CGCORGREST。这是一个完美的解决方案!你能解释一下CARATS的进展吗?我想我以前没有见过这种语法。@ ViTrEngEL,<代码> UICOLOR *(^ CurrutCultOrgBuffic)(UICOROR *)=^(UICOROR *颜色)…
正在声明一个
。有关iOS中块的介绍,请参阅我一直使用块,但我以前从未见过这样的语法。我想可能我没有使用返回对象的块。我发布的是=左侧的内容。这可能不适用于作为图案颜色的边缘情况。如果颜色是兼容的颜色,请从doc开始如果颜色不在兼容的颜色空间中,则参数不变。因此,您可以
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)
}
- (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];
}
BOOL equalColors = CGColorEqualToColor(uiColor1.CGColor, uiColor2.CGColor));
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
}
}
UIColor.whiteColor == UIColor(hex: "#FFFFFF") // true
UIColor.black == UIColor(red: 0, green: 0, blue: 0, alpha: 1) // true