2

是否可以实现EncodableDecodable属性UIColor

当我尝试添加Decodable扩展时出现错误

extension UIColor : Decodable {
    public required init(from decoder: Decoder) throws {
        self.init(red: 1, green: 1, blue: 1, alpha: 1)
    }
}

错误:ColorStuff.playground:98:21:错误:初始化程序要求“init(from:)”只能由required非最终类“UIColor”的定义中的初始化程序满足 public required init(来自解码器:解码器)抛出 {

我在这里遗漏了一些明显的东西吗?

我对Encodable扩展没有任何问题 - 这似乎是一个Decodable问题。

UIColor错误消息向我暗示,由于无法访问类定义,我无法执行此操作

4

1 回答 1

15

由于编译器给出的错误,您无法在扩展中UIColor遵循。Decodable

一种解决方案是制作一个Codable包装器类型并改用它。

既然UIColor已经符合NSCoding,让我们编写一个泛型类型,这样我们就可以对符合 的任何内容进行编码和解码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)
于 2018-02-01T16:41:33.483 回答