Parse UIColor from Json file with Codable (Swift)

天涯浪子 提交于 2020-06-27 08:05:09

问题


Im trying to decode a json file, and i have alot of ui configurations there, and im looking for a clean solution to parse directly a hex code to UIColor. But UIColor doesnt conform to Codable.

For example this json:

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

and i want to be able to do this:

struct Settings: Decodable {
    var color: UIColor
}

and while im decoding convert the "hex" string into a UIColor

I already have this function to decode from a String and return a 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
    }
}

For this to work i need to decode it manually by getting the container and decode it, but since i have alot of configurations my class will be huge because i need to set everything:

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)
   }
}

In the end im looking for a much cleaner way to do this. The ideal way is to turn UIColor codable (but i think i cant do that)

Thanks in advance


回答1:


What I did to solve this problem is to introduce a new Color type that conforms to the Decodable protocol and wraps a single UIColor property:

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
    }
}

Then you would use it like this:

cell.textLabel?.textColor = settings.color.value

That's for UIColor only, if you want to make it work for any type that doesn't conform to the Decodable protocol, John Sundell describes a generic approach in Customizing Codable types in Swift.




回答2:


If you are looking for a function that can convert a RGB hexcode to UIColor then use this.

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)
    )
}

Usage:

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

This will return a UIColor for the hex code "#ffb80c"



来源:https://stackoverflow.com/questions/53619084/parse-uicolor-from-json-file-with-codable-swift

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!