簡體   English   中英

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

[英]Parse UIColor from Json file with Codable (Swift)

我正在嘗試解碼一個 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 變為可編碼(但我認為我不能這樣做)

提前致謝

我為解決這個問題所做的是引入一個新的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 中描述了一種通用方法。

如果您正在尋找可以將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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM