【问题标题】:Parse UIColor from Json file with Codable (Swift)使用 Codable (Swift) 从 Json 文件中解析 UIColor
【发布时间】:2019-05-06 05:48:56
【问题描述】:

我正在尝试解码一个 json 文件,我在那里有很多 ui 配置,我正在寻找一个干净的解决方案来直接将十六进制代码解析为 UIColor。但是 UIColor 不符合 Codable。

例如这个json:

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

我希望能够做到这一点:

struct Settings: Decodable {
    var color: UIColor
}

在解码时将“十六进制”字符串转换为 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 可编码(但我认为我不能这样做)

提前致谢

【问题讨论】:

标签: ios json iphone 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

【讨论】:

  • 感谢您的回复,但我不是在寻找那个,正如我所说,我正在寻找一种使用十六进制代码从 json 解码 UIColor 的方法
【解决方案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 在Customizing Codable types in Swift 中描述了一种通用方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-14
    • 1970-01-01
    • 1970-01-01
    • 2020-07-28
    • 1970-01-01
    相关资源
    最近更新 更多