【问题标题】:Implementing Codable for UIColor为 UIColor 实现 Codable
【发布时间】:2018-07-11 23:54:27
【问题描述】:

是否可以为UIColor 实现EncodableDecodable 属性

当我尝试添加 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:)”只能由非最终类“UIColor”定义中的 required 初始化器满足 public required init(来自解码器:解码器)抛出 {

我在这里遗漏了什么明显的东西吗?

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

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

【问题讨论】:

  • 你错过了这个明显的错误:'required' initializer must be declared directly in class 'UIColor' (not in an extension)
  • 是的,这就是我所害怕的——正如最后一句话所说。所以我们称之为响亮的 NO WAY JOSE
  • 您可以随时尝试subclass 并让子类实现Codable。或者为它写一个包装器。

标签: ios swift swift4 decodable


【解决方案1】:

由于编译器给出的错误,您不能使 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)

【讨论】:

  • 如果我尝试使用具有单个值的(优秀)包装器,它会在编码时引发错误 - 即 - jsonData = try! JSONEncoder().encode([w]) 成功 let jsonData = try! JSONEncoder().encode(w) 失败并出现 let w = WrapperOfNSCoding(colors[0]) 错误是致命错误:'try!'表达式意外引发错误:Swift.EncodingError.invalidValue(WrapperOfNSCoding #1... 为什么会这样
  • 如果您发布自己的顶级问题,我将很乐意为您提供帮助。如果您愿意,请随时在此处添加评论链接。
猜你喜欢
  • 2019-05-06
  • 2021-08-29
  • 2019-04-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-26
相关资源
最近更新 更多