使用 Codable(Swift)从 Json 文件解析 UIColor

7

我将尝试翻译一个JSON文件,其中包含许多UI配置,并寻找一种干净的解决方案,以直接将十六进制代码解析为UIColor。但是UIColor不符合Codable。

例如,这个JSON:

var json = """
{
    "color": "#ffb80c"
}
""".data(using: .utf8)!

我希望您能够实现以下功能:

我想要能够做到这一点:

struct Settings: Decodable {
    var color: UIColor
}

在解码的同时将“hex”字符串转换为UIColor。

我已经有了这个从字符串解码并返回UIColor的函数:

public extension KeyedDecodingContainer {

    public func decode(_ type: UIColor.Type, forKey key: Key) throws -> UIColor {

        let colorHexString = try self.decode(String.self, forKey: key)
        let color = UIColor(hexString: colorHexString)

        return color
    }
}

为了使其正常工作,我需要手动解码容器并对其进行解码,但由于我有很多配置,所以我的类将会非常庞大,因为我需要设置所有内容。
struct Settings: Decodable {

    var color: Color

    enum CodingKeys: CodingKey {

        case color
    }

   init(from decoder: Decoder) throws {

        let container = try decoder.container(keyedBy: CodingKeys.self)

        color = try container.decode(UIColor.self, forKey: .color)
   }
}

最终,我希望找到一种更加简洁的方法来实现这个。理想的方式是将UIColor编码(但我认为我做不到)。

提前感谢。


3
可能是与为UIColor实现Codable重复的问题。 - Jacob Lange
2个回答

2
我解决这个问题的方法是引入一个新的Color类型,符合Decodable协议,并包装了一个单一的UIColor属性。
struct Color : Decodable {
    let value: UIColor

    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        let string = try container.decode(String.self)
        self.value = try UIColor(rgba_throws: string) // From https://github.com/yeahdongcn/UIColor-Hex-Swift
    }
}

然后你会像这样使用它:
cell.textLabel?.textColor = settings.color.value

这仅适用于 UIColor,如果您想使它适用于任何不符合 Decodable 协议的类型,John Sundell 在 Swift 中自定义 Codable 类型 中描述了一种通用方法。

-1
如果你正在寻找一个可以将RGB十六进制代码转换为UIColor的函数,请使用这个。
func hexStringToUIColor (hex:String) -> UIColor {
    var cString:String = hex.trimmingCharacters(in: .whitespacesAndNewlines).uppercased()
    if (cString.hasPrefix("#")) {
        cString.remove(at: cString.startIndex)
    }
    if ((cString.count) != 6) {
        return UIColor.gray
    }
    var rgbValue:UInt32 = 0
    Scanner(string: cString).scanHexInt32(&rgbValue)
    return UIColor(
        red: CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0,
        green: CGFloat((rgbValue & 0x00FF00) >> 8) / 255.0,
        blue: CGFloat(rgbValue & 0x0000FF) / 255.0,
        alpha: CGFloat(1.0)
    )
}

使用方法:

let color = hexStringToUIColor (hex: ""#ffb80c")

这将返回一个十六进制代码为"#ffb80c"的UIColor颜色


2
谢谢您的回复,但我不是在寻找那个,正如我所说,我正在寻找一种使用十六进制代码从JSON解码UIColor的方法。 - Ricardo Costa

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