現在、データを格納する Core Data データベースがあり、そこに NSColor も格納したいのですが、NSColor をオブジェクトとして受け入れません。私の解決策は、データベースに文字列として保存し、ロード時に NSColor に読み込むことです。どうすればいいですか?
たとえば[NSColor redColor]
、データベースに(文字列として)保存してから取得する方法のような色があった場合。これは基本的な例であり、最終的にはより複雑な RGB カラーになります。
ありがとう。
現在、データを格納する Core Data データベースがあり、そこに NSColor も格納したいのですが、NSColor をオブジェクトとして受け入れません。私の解決策は、データベースに文字列として保存し、ロード時に NSColor に読み込むことです。どうすればいいですか?
たとえば[NSColor redColor]
、データベースに(文字列として)保存してから取得する方法のような色があった場合。これは基本的な例であり、最終的にはより複雑な RGB カラーになります。
ありがとう。
Core Data でサポートされていないデータ型を格納するためのコンテナーとして NSData を使用することを検討する必要があります。NSColor を NSData としてアクセスするには、属性を変換可能としてマークし、可逆的な NSValueTransformer クラスを作成して NSColor を NSData として変換する必要があります。
役立つリンク:非標準の永続属性
Core Data ストアに色を保存するために 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 は色を NSString としてではなく NSData として保存することを推奨しています。おそらく同じことを行う必要があります。Apple の指示については、こちらを参照してください。
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
}