ios 如何比较 UIColors?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/970475/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to compare UIColors?
提问by 4thSpace
I'd like to check the color set for a background on a UIImageView. I've tried:
我想检查 UIImageView 上背景的颜色设置。我试过了:
if(myimage.backgroundColor == [UIColor greenColor]){
...}
else{
...}
but that doesn't work, even when I know the color is green, it always falls into the else part.
但这不起作用,即使我知道颜色是绿色,它也总是落入 else 部分。
Also, is there a way to output the current color in the debug console.
另外,有没有办法在调试控制台中输出当前颜色。
p [myimage backgroundColor]
and
和
po [myimage backgroundColor]
don't work.
不工作。
回答by Steven Canfield
Have you tried [myColor isEqual:someOtherColor]
?
你试过[myColor isEqual:someOtherColor]
吗?
回答by samvermette
As zoul pointed out in the comments, isEqual:
will return NO
when comparing colors that are in different models/spaces (for instance #FFF
with [UIColor whiteColor]
). I wrote this UIColor extension that converts both colors to the same color space before comparing them:
正如 zoul 在评论中指出的那样,isEqual:
将NO
在比较不同模型/空间中的颜色时返回(例如#FFF
与[UIColor whiteColor]
)。我写了这个 UIColor 扩展,在比较它们之前将两种颜色转换为相同的颜色空间:
- (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];
}
回答by DZenBot
This might be a bit too late, but CoreGraphics has an easier API to achieve this:
这可能有点晚了,但 CoreGraphics 有一个更简单的 API 来实现这一点:
CGColorEqualToColor(myColor.CGColor, [UIColor clearColor].CGColor)
Like the documentation says:
就像文档说的:
Indicates whether two colors are equal. Two colors are equal if they have equal color spaces and numerically equal color components.
指示两种颜色是否相等。如果两种颜色具有相等的颜色空间和数值上相等的颜色分量,则它们是相等的。
This solves a lot trouble and leaking/custom algorithms.
这解决了很多麻烦和泄漏/自定义算法。
回答by raf
samvermette's solution translated to swift:
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
}
}
}
回答by Viktor Goltvyanitsa
#import "UIColor-Expanded.h"
//https://github.com/thetaplab/uicolor-utilities
//RGB distance
CGFloat distance = sqrtf(powf((clr0.red - clr1.red), 2) + powf((clr0.green - clr1.green), 2) + powf((clr0.blue - clr1.blue), 2) );
if(distance<=minDistance){
....
}else{
...
}
回答by boherna
This UIColor extension works fine provided that the compared colors can be converted into RGB format, which should be most of the cases.
只要比较的颜色可以转换为 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
}
}
At least with this extension:
至少有了这个扩展:
UIColor.whiteColor == UIColor(hex: "#FFFFFF") // true
UIColor.black == UIColor(red: 0, green: 0, blue: 0, alpha: 1) // true
Both comparisons would return false if compared using the native UColor.isEqual(...)
如果使用本机 UColor.isEqual(...) 进行比较,则两种比较都将返回 false
回答by vikingosegundo
I wrote this category. If isEqual:
does return NO, it will test if further comparison of different components might still match. If possible, different models are still compared.
我写了这个类。如果isEqual:
确实返回 NO,它将测试不同组件的进一步比较是否仍然匹配。如果可能,仍然比较不同的模型。
@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
UIColor *green1 = [UIColor greenColor];
UIColor *green2 = [UIColor colorWithRed:0 green:1 blue:0 alpha:1];
UIColor *yellow = [UIColor yellowColor];
UIColor *grey1 = [UIColor colorWithWhite:2.0/3.0 alpha:1];
UIColor *grey2 = [UIColor lightGrayColor];
NSError *error1, *error2, *error3, *error4, *error5;
BOOL match1 = [green1 matchesColor:green2 error:&error1]; // YES
BOOL match2 = [green1 matchesColor:yellow error:&error2]; // NO
BOOL match3 = [green1 matchesColor:grey1 error:&error3]; // NO
BOOL match4 = [grey1 matchesColor:grey2 error:&error4]; // YES
BOOL match5 = [grey1 matchesColor:[UIColor colorWithPatternImage:[UIImage imageNamed:@"bg.png"]]
error:&error5]; // NO, Error
回答by mert
When you're comparing
myimage.backgroundColor == [UIColor greenColor]
like this if you havent change the backgroundColor to green before that statement it is not working.
当您进行
myimage.backgroundColor == [UIColor greenColor]
这样的比较时,如果您在该语句之前没有将 backgroundColor 更改为绿色,则它不起作用。
I had same problem in my color game and i solved that by using simple difference equation in RGB colors you can quick take a look that short code sample ColorProcess from here
我在我的颜色游戏中遇到了同样的问题,我通过在 RGB 颜色中使用简单的差分方程解决了这个问题,您可以从这里快速查看短代码示例 ColorProcess
its like victors answer
它就像胜利者的答案
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{
…
}
Instead of that code sample you can use
您可以使用该代码示例而不是
include "UIColorProcess.h"
..
float distance = [UIColorProcess findDistanceBetweenTwoColor:[UIColor redColor] secondColor:[UIColor blueColor]];
and of course if it returns 0 that means you are comparing too similar color. return range is something like (0.0f - 1.5f)..
当然,如果它返回 0,则意味着您正在比较太相似的颜色。返回范围类似于 (0.0f - 1.5f)..
回答by Pbk
Some weird rounding errors can occur. That can be the reason a object set to a color and the color you set it to do not match exactly.
可能会发生一些奇怪的舍入错误。这可能是对象设置的颜色与您设置的颜色不完全匹配的原因。
This is how I solved it:
我是这样解决的:
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))
}
This code can be improved by not only comparing 1 but comparing all the components. Eg red+green+blue+alpha == red2+green2+blue2+alpha2
不仅可以通过比较 1 还可以通过比较所有组件来改进此代码。例如红色+绿色+蓝色+alpha == red2+green2+blue2+alpha2
回答by arunit21
I'm using this extension which is working for me in all cases.
我正在使用这个扩展程序,它在所有情况下都对我有用。
/***** 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 ****/
Hope helps some one.
希望对某人有所帮助。
Note: #ffffff
does equal [UIColor whiteColor]
by this extension
注意:此扩展名#ffffff
等于[UIColor whiteColor]