iPhone iOS如何将UIColor序列化/保存到JSON文件中?

6
当我需要将颜色保存到core data中时,我通常使用NSKeyedArchiever来进行转换,然后在需要加载实体时再解档颜色。然而,当我尝试将core data实体序列化时,该过程失败了,因为它不知道如何将keyed archiever的NSData转换为字符串。
如何将UIColor转换为字符串表示形式以在JSON文件中发送?一种解决方案是将r、g、b、a值存储为浮点数。还有一种解决方案是将其保存为十六进制字符串。这两种方法似乎都会使恢复颜色的过程变得更加复杂。
我是否漏掉了什么?是否有更简单的方法在JSON中序列化UIColor?
6个回答

5

你觉得怎么样:

NSDictionary *colorData = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithFloat:100.f], @"Red",
                               [NSNumber numberWithFloat:24.f], @"Green",
                               [NSNumber numberWithFloat:23.f], @"Blue",
                               [NSNumber numberWithFloat:1.f], @"Alpha", nil];

NSDictionary *color = [NSDictionary dictionaryWithObject:colorData forKey:@"Color"];

结果大致如下:
{"Color":{"Green":24,"Alpha":1,"Blue":23,"Red":100}}

您可以轻松地创建一个方法,该方法以UIColor作为参数并返回一个可直接序列化的NSDictionary。反向过程是相同的。


如果颜色是从图案图像中创建的呢? - jjxtra
然后只保存图像的路径。 - graver

2

这取决于是否有“私有”颜色格式的自由。一些颜色不适合要求 RGBA(这就是为什么 get... 方法返回一个 BOOL -- 它们并不总是成功),因此该实现包括颜色类型以及值。

@implementation UIColor (JSON)

- (NSString *)json_stringValue
{
    CGFloat r, g, b, a, h, s, w;
    if ([self getRed:&r green:&g blue:&b alpha:&a]) 
        return [NSString stringWithFormat:@"rgba:%f,%f,%f,%f", r,g,b,a];
    else if ([self getHue:&h saturation:&s brightness:&b alpha:&a])
        return [NSString stringWithFormat:@"hsba:%f,%f,%f,%f", h,s,b,a];
    else if ([self getWhite:&w alpha:&a]) 
        return [NSString stringWithFormat:@"wa:%f,%f", w, a];

    NSLog(@"WARNING: unable to serialize color %@", self);
    return nil;
}

@end

@implementation NSString (JSON)

- (UIColor *)json_color
{
    NSArray *comps = [self componentsSeparatedByString:@":"];
    NSArray *colors = [comps[1] componentsSeparatedByString:@","];
    NSUInteger count = colors.count;
    CGFloat values[4] = {0,0,0,0};
    for (NSUInteger i = 0; i < count; i++) values[i] = [colors[i] floatValue];

    if ([comps[0] isEqualToString:@"rgba"]) 
        return [UIColor colorWithRed:values[0] green:values[1] blue:values[2] alpha:values[3]];
    else if ([comps[0] isEqualToString:@"hsba"])
        return [UIColor colorWithHue:values[0] saturation:values[1] brightness:values[2] alpha:values[3]];
    else if ([comps[0] isEqualToString:@"wa"])
        return [UIColor colorWithWhite:values[0] alpha:values[1]];

    NSLog(@"WARNING: unable to deserialize color %@", self);
    return nil;
}

@end

2

由于没有一个定义的标准来在JSON中放置UIColor(更不用说一个通用的“颜色”),因此您需要自己解决。

我建议最好的方法是在UIColor上创建一个类别,该类别为您提供RGB颜色空间中颜色的标准十六进制代码,并接受这样的十六进制代码并输出UIColor。然后在JSON中传输该十六进制代码。

我知道这可能看起来有点过度,但这是迄今为止最便携和紧凑的解决方案。

可以在我的MJGFoundation UIColor类别中找到十六进制到UIColor方法的示例。编写类似于将UIColor转换为十六进制值的方法也不太难,但请注意首先将其转换为RGBA颜色空间。


2
我找到的解决方案是从UIColor创建CIColor,然后再转换回去:
将其转换为字符串:
CIColor(color: UIColor.blue).stringRepresentation

转换为颜色:

UIColor(ciColor: CIColor(string: databaseColorString))

最简单的解决方案 - Miguel Gallego

0
将两个答案结合起来,得到以下结果:
要保存:
#import "UIColor-HSVAdditions.h"
#import "JSONKit.h"

UIColor* color = textView.textColor;
            NSDictionary *colorData = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithFloat:color.hue], @"Hue",
                                       [NSNumber numberWithFloat:color.saturation], @"Saturation",
                                       [NSNumber numberWithFloat:color.brightness], @"Brightness",
                                       [NSNumber numberWithFloat:color.alpha], @"Alpha", nil];

            NSString* jsonString = [colorData JSONString];

加载:

 NSDictionary* dictionary = [coreDataEntity.fontColor objectFromJSONString];

                    NSNumber* hue =[dictionary objectForKey:kHueKey];
                    NSNumber* saturation =[dictionary objectForKey:kSaturationKey];
                    NSNumber* brightness =[dictionary objectForKey:kBrightnessKey];
                    NSNumber* alpha =[dictionary objectForKey:kAlphaKey];

                    UIColor* color = [UIColor colorWithHue:hue.floatValue saturation:saturation.floatValue brightness:brightness.floatValue alpha:alpha.floatValue];

                    textView.textColor = color;

0

我已经创建了一个Swift Package来帮助解决这个问题!

import SerializationTools

let exampleColor = UIColor.systemRed

let colorJsonString = try exampleColor.codable.jsonString()
// This ends up being a Base64 UTF-8 string representing the `NSCoding` representation

let recreatedColor = try UIColor.CodableBridge(jsonString: colorJsonString).value

这样可以保留像.label.systemBackground这样的花哨魔幻颜色!

您可以在此处获取它:https://github.com/RougeWare/Swift-SerializationTools


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接