WrapperOfNSCoding失败,具有单个值

时间:2018-03-16 23:14:48

标签: swift codable

来自Implementing Codable for UIColor的问题

    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 = [NSColor.red, NSColor.brown]
    print(colors)
    let w = WrapperOfNSCoding(colors[0])
    let jsonData = try! JSONEncoder().encode(w) - fails
    let jsonData = try! JSONEncoder().encode(colors.map({ WrapperOfNSCoding($0) })) - succeeds

    print(jsonData)
    let colors2 = try! JSONDecoder().decode([WrapperOfNSCoding<NSColor>].self, from: jsonData).map({ $0.wrapped })
    print(colors2)

错误是在编码器中使用单个值时

let w = WrapperOfNSCoding(colors[0])
let jsonData = try! JSONEncoder().encode(w)

错误是

  

致命错误:&#39;尝试!&#39;表达式意外地引发了一个错误:   Swift.EncodingError.invalidValue(WrapperOfNSCoding#1 ......

这成功了

let w = WrapperOfNSCoding([colors[0]])
let jsonData = try! JSONEncoder().encode(w)

为什么会这样?

1 个答案:

答案 0 :(得分:2)

JSONEncoder在顶级需要有效的JSON上下文,可以是[:](字典)或[](数组),你可以在里面放置一个像这个例子中的元素{ {1}}。

当您保存任何string对象时,编译器会将该对象视为字符串。在NSCoding的情况下,您尝试编码JSONEncoder().encode(w)对象,该对象充当NSCoding对象而不是常规string对象。

JSON的情况下,对象创建了一个数组,并且每个元素都有一个字符串,在您的情况下为JSONEncoder().encode([w])

另一种方式NSCoding数据是一个字符串,w是一个数组,每个索引都有一个字符串,因此[w]没有给你JSONEncoder错误并为[w]提供错误。