【问题标题】:Store a NSColor as a string将 NSColor 存储为字符串
【发布时间】:2012-06-08 22:34:38
【问题描述】:

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

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

谢谢。

【问题讨论】:

    标签: objective-c core-data


    【解决方案1】:

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

    有用链接:Non-Standard Persistent Attributes

    【讨论】:

      【解决方案2】:

      我同意建议使用 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 windowBackgroundColor] 的字符串表示时;我收到一些错误 -getComponents: not valid for the NSColor Catalog color: System windowBackgroundColor;需要先转换色彩空间。
      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

        属性列表不存储颜色,Apple 建议您将它们存储为 NSData 而不是 NSString,您可能应该这样做。请参阅 Apple 的说明 here

        【讨论】:

          【解决方案5】:

          以下是用于将NSColor 转换为NSString 和从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
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2018-11-29
            • 2010-10-20
            • 2012-05-02
            • 2020-06-20
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多