Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parse UIColor from Json file with Codable (Swift)

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

like image 884
Ricardo Costa Avatar asked Dec 04 '18 18:12

Ricardo Costa


People also ask

What is Codable and Codable in Swift?

Codable; the data-parsing dream come true!Codable is the combined protocol of Swift's Decodable and Encodable protocols. Together they provide standard methods of decoding data for custom types and encoding data to be saved or transferred.

What is Codable class in Swift?

Understanding what Swift's Codable is The Codable protocol in Swift is really a union of two protocols: Encodable and Decodable . These two protocols are used to indicate whether a certain struct, enum, or class, can be encoded into JSON data, or materialized from JSON data.


1 Answers

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.

like image 160
0xced Avatar answered Sep 24 '22 18:09

0xced