我目前有一个存储数据的核心数据数据库,我还希望将 NSColor 存储到其中,但它不接受 NSColor 作为对象。我的解决方案是将其作为字符串存储在数据库中,并在加载时将其读入 NSColor。我该怎么做?
例如,如果我有一种颜色,[NSColor redColor]
我将如何将它存储在数据库中(作为字符串)然后检索它。这是一个基本示例,最终将是更复杂的 RGB 颜色。
谢谢。
我目前有一个存储数据的核心数据数据库,我还希望将 NSColor 存储到其中,但它不接受 NSColor 作为对象。我的解决方案是将其作为字符串存储在数据库中,并在加载时将其读入 NSColor。我该怎么做?
例如,如果我有一种颜色,[NSColor redColor]
我将如何将它存储在数据库中(作为字符串)然后检索它。这是一个基本示例,最终将是更复杂的 RGB 颜色。
谢谢。
您应该考虑使用 NSData 作为在 Core Data 中存储不受支持的数据类型的容器。要将 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,您可能应该这样做。请在此处查看 Apple 的说明。
以下是用于将 a 转换NSColor
为 和从NSString
. 此示例假设我们使用的是 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
}