是否可以实现Encodable和的Decodable属性UIColor
Encodable
Decodable
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必需init(from解码器:Decoder)抛出{
required
我在这里错过明显的东西吗?
Encodable扩展名没有问题-似乎是个Decodable问题。
该错误消息向我暗示由于无法访问UIColor类定义而无法执行此操作
由于编译器给出的错误,您不能使扩展UIColor符合Decodable。
一种解决方案是创建Codable包装器类型,然后使用它。
Codable
由于UIColor已经符合NSCoding,我们只需要编写一个通用类型,就可以对符合的任何内容进行编码和解码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)