Chciałbym sprawdzić zestaw kolorów dla tła w UIImageView. Próbowałem:
if(myimage.backgroundColor == [UIColor greenColor]){
...}
else{
...}
ale to nie działa, nawet jeśli wiem, że kolor jest zielony, zawsze wpada w inną część.
Czy istnieje również sposób na wyświetlenie bieżącego koloru w konsoli debugowania.
p [myimage backgroundColor]
i
po [myimage backgroundColor]
nie działa.
ios
objective-c
cocoa-touch
uiimageview
uicolor
4thSpace
źródło
źródło
ffffff
nie jest równe[UIColor whiteColor]
.Jak zauważył Zoul w komentarzach,
isEqual:
powróciNO
podczas porównywania kolorów, które są w różnych modelach / przestrzeniach (na przykład#FFF
z[UIColor whiteColor]
). Napisałem to rozszerzenie UIColor, które konwertuje oba kolory na tę samą przestrzeń kolorów przed ich porównaniem:- (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]; }
źródło
UIColor *(^convertColorToRGBSpace)(UIColor*) = ^(UIColor *color) ...
deklaruje plikblock
. Używa go później zconvertColorToRGBSpace(self)
. Aby zapoznać się z wprowadzeniem do bloków w iOS, zobacz raywenderlich.com/9328/creating-a-diner-app-using-blocks-part-1To może być trochę za późno, ale CoreGraphics ma łatwiejszy interfejs API, aby to osiągnąć:
CGColorEqualToColor(myColor.CGColor, [UIColor clearColor].CGColor)
Jak mówi dokumentacja:
To rozwiązuje wiele problemów i nieszczelnych / niestandardowych algorytmów.
źródło
[UIColor isEqual:]
robi to samo, prawda? Odpowiedź Marka jest nadal jedyną, która sprawdza równoważność pomimo dobrej przestrzeni kolorów.UIColor isEqual:
gdyby kolory były w różnych przestrzeniach kolorów.rozwiązanie samvermette przetłumaczone na szybkie:
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 } } }
źródło
#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{ ... }
źródło
To rozszerzenie UIColor działa dobrze, pod warunkiem, że porównywane kolory można przekonwertować na format RGB, co powinno być w większości przypadków.
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 } }
Przynajmniej z tym rozszerzeniem:
UIColor.whiteColor == UIColor(hex: "#FFFFFF") // true UIColor.black == UIColor(red: 0, green: 0, blue: 0, alpha: 1) // true
Oba porównania zwróciłyby fałsz, gdyby porównać je przy użyciu natywnego UColor.isEqual (...)
źródło
Napisałem tę kategorię. Jeśli
isEqual:
zwróci NIE, sprawdzi, czy dalsze porównanie różnych składników może nadal pasować. Jeśli to możliwe, nadal porównuje się różne modele.@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
źródło
Miałem ten sam problem w mojej grze w kolory i rozwiązałem to używając prostego równania różnicowego w kolorach RGB, możesz szybko rzucić okiem na ten krótki kod ColorProcess stąd
to jak odpowiedź zwycięzców
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{ … }
Zamiast tego przykładowego kodu możesz użyć
include "UIColorProcess.h" .. float distance = [UIColorProcess findDistanceBetweenTwoColor:[UIColor redColor] secondColor:[UIColor blueColor]];
i oczywiście jeśli zwraca 0, oznacza to, że porównujesz zbyt podobny kolor. zakres zwrotny jest mniej więcej taki jak (0,0f - 1,5f).
źródło
Mogą wystąpić dziwne błędy zaokrągleń. Może to być powód, dla którego obiekt został ustawiony na kolor, a kolor, który ustawiłeś, nie pasuje dokładnie.
Oto jak to rozwiązałem:
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)) }
Ten kod można ulepszyć nie tylko porównując 1, ale porównując wszystkie komponenty. Np. Czerwony + zielony + niebieski + alpha == red2 + green2 + blue2 + alpha2
źródło
Używam tego rozszerzenia, które działa dla mnie we wszystkich przypadkach.
/***** 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 ****/
Nadzieja komuś pomaga.
Uwaga:
#ffffff
równa się[UIColor whiteColor]
przez to rozszerzenieźródło
Co powiesz na:
+(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); }
źródło
-1
a jeśli któryś z nich nadal ma tę wartość po wywołaniugetRed:green:blue:alpha:
, wiesz, że porównanie nie powiodło się. (lub nie pomijaj zwróconej wartości logicznej, ponieważ powie ci, czy została pomyślnie wywołana.)getRed:free:blue:alpha:
nie powiedzie się na monochromatycznym kolorze. Więc twój kod nie da innego wyniku niżis equal:
. zobacz moją odpowiedź, jak sobie z tym poradzić.Oto rozszerzenie umożliwiające przejście do RGC Space Color w Swift:
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 }
}
źródło
Rozszerzenie do UIColor przy użyciu funkcji Swift 2.2. Zwróć jednak uwagę, że ponieważ wartości RGBA są porównywane, a są to CGFloat, błędy zaokrąglania mogą spowodować, że kolory nie są zwracane jako równe, jeśli nie są dokładnie takie same (np. Nie zostały pierwotnie utworzone przy użyciu tych samych właściwości w 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 }
źródło
Rozszerzenie 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; }
źródło
Mam przeliczone odpowiedź RAF do Swift 4 (wiele zmian w
CGColor
API) usuniętego siły odpakowanie i zmniejszyła wcięcia dzięki hojnym wykorzystaniaguard
:@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) } }
źródło
Dlaczego nie dodać rozszerzenia z równoważnym protokołem? Ta odpowiedź wykorzystuje rozwiązanie Nicolasa Miari. Jeśli więc podoba Ci się ta odpowiedź, zapraszam do polubienia jego odpowiedzi (druga od góry)
Komentarz Zoula: Zachowaj ostrożność podczas porównywania kolorów w ten sposób, ponieważ muszą one być w tym samym modelu kolorów, aby można je było uznać za równe. Na przykład #ffffff nie równa się [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) }
źródło
Chociaż odpowiedź @ samvermette jest bardzo dobra, odkryłem, że czasami może to prowadzić do fałszywych negatywów podczas porównywania różnych typów kolorów (w moim przypadku
UIDeviceRGBColor
doUICachedDeviceWhiteColor
). Naprawiłem to, jawnie tworząc kolor w elemencie „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]; }
źródło
Musisz użyć
BOOL equalColors = CGColorEqualToColor(uiColor1.CGColor, uiColor2.CGColor));
Dokumentacja tutaj .
źródło
Przeczytałem i wypróbowałem wszystkie odpowiedzi na tej stronie, myślę, że boheras jest najlepszy, dopracowałem go i oto jest:
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 } }
możesz tego użyć w ten sposób: (cytat z bohery)
UIColor.whiteColor == UIColor(hex: "#FFFFFF") // true UIColor.black == UIColor(red: 0, green: 0, blue: 0, alpha: 1) // true
źródło
if([myimage.backgroundColor isEqual:[UIColor greenColor]])
źródło