Implementing Codable for UIColor

前端 未结 1 1486
不思量自难忘°
不思量自难忘° 2020-12-11 14:01

Is it possible to implement the Encodable and Decodable properties for UIColor

When I try to add a Decodable exte

相关标签:
1条回答
  • 2020-12-11 14:21

    You cannot make UIColor conform to Decodable in an extension because of the error given by the compiler.

    One solution is to make a Codable wrapper type and use that instead.

    Since UIColor already conforms to NSCoding, let's just write a generic type so we can encode and decode anything that conforms to NSCoding.

    import UIKit
    
    struct WrapperOfNSCoding<Wrapped>: Codable where Wrapped: NSCoding {
        var wrapped: Wrapped
    
        init(_ wrapped: Wrapped) { self.wrapped = wrapped }
    
        init(from decoder: Decoder) throws {
            let container = try decoder.singleValueContainer()
            let data = try container.decode(Data.self)
            guard let object = NSKeyedUnarchiver.unarchiveObject(with: data) else {
                throw DecodingError.dataCorruptedError(in: container, debugDescription: "failed to unarchive an object")
            }
            guard let wrapped = object as? Wrapped else {
                throw DecodingError.typeMismatch(Wrapped.self, DecodingError.Context(codingPath: container.codingPath, debugDescription: "unarchived object type was \(type(of: object))"))
            }
            self.wrapped = wrapped
        }
    
        func encode(to encoder: Encoder) throws {
            let data = NSKeyedArchiver.archivedData(withRootObject: wrapped)
            var container = try encoder.singleValueContainer()
            try container.encode(data)
        }
    }
    
    let colors = [UIColor.red, UIColor.brown]
    print(colors)
    let jsonData = try! JSONEncoder().encode(colors.map({ WrapperOfNSCoding($0) }))
    let colors2 = try! JSONDecoder().decode([WrapperOfNSCoding<UIColor>].self, from: jsonData).map({ $0.wrapped })
    print(colors2)
    
    0 讨论(0)
提交回复
热议问题