UIColor 相等性在将其存储在 NSUserDefaults 后失败

UIColor equality fails after storing it in NSUserDefaults

我在 NSUserDefaults 中存储了一个 UIColor,我遇到的问题是在检索颜色时简单的相等性检查失败(对于我的测试)。有人可以解释为什么这会失败吗?

UIColor *color = [UIColor colorWithRed: 0.922 green: 0.404 blue: 0.024 alpha: 1];
NSData *colorData = [NSKeyedArchiver archivedDataWithRootObject:color];

[[NSUserDefaults standardUserDefaults] setObject:colorData forKey:@"myColor"];

NSData *storedColorData = [[NSUserDefaults standardUserDefaults] objectForKey:@"myColor"];
UIColor *restoredColor = [NSKeyedUnarchiver unarchiveObjectWithData:storedColorData];

if ([color isEqual:restoredColor]) {
    NSLog(@"Same color");
} else {
    NSLog(@"Not the same color");
}

结果将是 "Not the same color"。在调试器中快速查看将显示颜色相同(RGB 和 alpha 值)。

也许这个问题可以帮到你:

您可以尝试使用 CGColorEqualToColor(color.CGColor, restoredColor.CGColor) 来比较颜色。

如果你NSLog两种颜色,你会发现两种颜色实际上是一样的!

NSLog(@"Color before: %@", color);
NSLog(@"Color after: %@", restoredColor);

// 2015-04-09 13:19:36.640 test[31149:6236981] Color before: UIDeviceRGBColorSpace 0.922 0.404 0.024 1
// 2015-04-09 13:19:36.641 test[31149:6236981] Color after: UIDeviceRGBColorSpace 0.922 0.404 0.024 1

因此您需要明确比较 UIColor 的每个组件,即 redgreenbluealpha

看看这个 answer


有趣的是,如果您记录这两种颜色的哈希值,它们看起来也一样

NSLog(@"Color Hash before: %lu", (unsigned long)[color hash]);
NSLog(@"Color Hash after: %lu", (unsigned long)[restoredColor hash]);

// 2015-04-09 13:59:06.097 test[31299:6252585] Color before: 137311944
// 2015-04-09 13:59:06.097 test[31299:6252585] Color after: 137311944

这样您就可以比较哈希并使其正常工作。

if(color.hash == restoredColor.hash) {
   // ...
}

如上面接受的答案所述,当您传入 double 值时,isEqualTo: 不起作用。 float 应改为传递值

UIColor *color = [UIColor colorWithRed:0.922f green:0.404f blue:0.024f alpha:1.0f];

如果你这样声明你的 UIColor:

UIColor *color = [UIColor colorWithRed: (float)0.922 green: (float)0.404 blue: (float)0.024 alpha: (float)1];

两种比较颜色的方法在你的例子中都是return YES:

[color isEqual:restoredColor]
CGColorEqualToColor(color.CGColor, restoredColor.CGColor)

更新:用于比较 UIColor 组件的类别

@interface UIColor (Compare)

- (BOOL)isEqualToColor:(UIColor *)otherColor;

@end

@implementation UIColor (Compare)

- (BOOL)isEqualToColor:(UIColor *)otherColor {
    const CGFloat *components = CGColorGetComponents(self.CGColor);
    float colorOne[4] = {components[0], components[1], components[2], components[3]};

    const CGFloat *otherComponents = CGColorGetComponents(otherColor.CGColor);
    float colorTwo[4] = {otherComponents[0], otherComponents[1], otherComponents[2], otherComponents[3]};

    return colorOne[0] == colorTwo[0] && colorOne[1] == colorTwo[1] && colorOne[2] == colorTwo[2] && colorOne[3] == colorTwo[3];
}

@end