将 NSColor 存储为字符串



我目前有一个存储数据的核心数据数据库,我希望也将NSColor存储到其中,但它不接受NSColor作为对象。我的解决方案是将其作为字符串存储在数据库中,并在加载时将其读入 NSColor。我该怎么做?

例如,如果我有像[NSColor redColor]这样的颜色,我将如何将其存储在数据库中(作为字符串),然后检索它。这是一个基本示例,最终会更加复杂的RGB颜色。

谢谢。

您应该考虑使用 NSData 作为容器,用于在核心数据中存储不受支持的数据类型。要将 NSColor 访问为 NSData,您需要将属性标记为可转换,并创建可逆的 NSValueTransformer 类以将 NSColor 转换为 NSData。

有用的链接:非标准持久属性

我同意建议使用 NSData 在核心数据存储中存储颜色的答案。也就是说,有时将颜色存储在字符串中可能很有用,这当然不难做到。我建议在NSColor上创建一个类别:

@interface NSColor (NSString)
- (NSString*)stringRepresentation;
+ (NSColor*)colorFromString:(NSString*)string forColorSpace:(NSColorSpace*)colorSpace;
@end
@implementation NSColor (NSString)
- (NSString*)stringRepresentation
{
    CGFloat components[10];
    [self getComponents:components];
    NSMutableString *string = [NSMutableString string];
    for (int i = 0; i < [self numberOfComponents]; i++) {
        [string appendFormat:@"%f ", components[i]];
    }
    [string deleteCharactersInRange:NSMakeRange([string length]-1, 1)]; // trim the trailing space
    return string;
}
+ (NSColor*)colorFromString:(NSString*)string forColorSpace:(NSColorSpace*)colorSpace
{
    CGFloat components[10];    // doubt any color spaces need more than 10 components
    NSArray *componentStrings = [string componentsSeparatedByString:@" "];
    int count = [componentStrings count];
    NSColor *color = nil;
    if (count <= 10) {
        for (int i = 0; i < count; i++) {
            components[i] = [[componentStrings objectAtIndex:i] floatValue];
        }
        color = [NSColor colorWithColorSpace:colorSpace components:components count:count];
    }
    return color;
}
@end

我已经检查了上面的代码是否按照广告编译和工作。一个小的示例程序会产生适当的输出:

int main(int argc, const char * argv[])
{
    @autoreleasepool {
        NSLog(@"Red is: %@", [[NSColor redColor] stringRepresentation]);
        NSLog(@"Cyan is: %@", [[NSColor cyanColor] stringRepresentation]);
        NSLog(@"Read in: %@", [NSColor colorFromString:[[NSColor redColor] stringRepresentation]
                                         forColorSpace:[NSColorSpace deviceRGBColorSpace]]);
    }
    return 0;
}

输出:

Red is: 1.000000 0.000000 0.000000 1.000000
Cyan is: 0.000000 1.000000 1.000000 1.000000
Read in: NSCustomColorSpace Generic RGB colorspace 1 0 0 1

将颜色空间存储在字符串中可能是有意义的,这样在从字符串转到颜色时就不必指定它。再说一次,如果您只是要存储这些字符串并再次读取它们,那么无论如何都应该使用 NSData。如果您需要将颜色写入某种人类可读的文件,或者作为调试辅助工具,则使用字符串更有意义。

NSColor支持 NSCoding 协议,因此您可以使用 -encodeWithCoder: 方法将其保存到存档中,也可以使用 -initWithCoder: 从存档加载它。

属性列表不存储颜色,Apple建议将它们存储为NSData而不是NSString,您可能也应该这样做。在此处查看苹果的说明。

以下是用于将NSColorNSString相互转换的简单函数。此示例假设我们使用的是 RGB 色彩空间,但是它可以很容易地适应其他人。 例如,NSStringFromColor()可以在字符串中包含颜色空间,并在转换回 NSColorFromString() 中的颜色时使用该信息。

用法:

NSString *theColorString = NSStringFromColor(theColor);
NSColor *theColor = NSColorFromString(theColorString);

功能:

NSString *NSStringFromColor(NSColor *theColor)
{
    CGFloat red, green, blue, alpha;
    [theColor getRed:&red green:&green blue:&blue alpha:&alpha]; // assumes RGB color space
    NSString *theColorString = [NSString stringWithFormat:@"%f %f %f %f",red,green,blue,alpha];
    return theColorString;
}
NSColor *NSColorFromString(NSString *theColorString)
{
    if ( theColorString.length == 0 ) {
        theColorString = @"0.9 0.9 0.95 1.0"; // a default color
    }
    NSArray <NSString *> *theColors = [theColorString componentsSeparatedByString:@" "];
    if ( theColors.count == 4 ) { // sanity
        // unpack the color
        NSColor *theColor = [NSColor colorWithSRGBRed:theColors[0].floatValue
                                                green:theColors[1].floatValue
                                                 blue:theColors[2].floatValue
                                                alpha:theColors[3].floatValue];
        return theColor;
    }
    return nil; // theColorString format error
}

相关内容

最新更新