问题
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