WrapperOfNSCoding fails with single value

落爺英雄遲暮 提交于 2019-12-13 20:07:19

问题


A question from 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)

The error is when a single value is used in the encoder

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

error is

Fatal error: 'try!' expression unexpectedly raised an error: Swift.EncodingError.invalidValue(WrapperOfNSCoding #1...

This succeeds

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

Why would that be


回答1:


JSONEncoder need valid JSON context on the top level, which could be either [:] (Dictionary) or [] (Array), inside you can place an element like in this example string.

When you save any NSCoding object, the compiler treats that object as the string. In the case of JSONEncoder().encode(w), you are trying to encode an NSCoding object which acts as a string object instead of regular JSON object.

In the case of JSONEncoder().encode([w]), the object has created an array and each element has a string which is NSCoding in your case.

In another way w data is a string and [w] is an array with each index is having a string, therefore JSONEncoder is not giving you an error with [w] and giving you an error for w.



来源:https://stackoverflow.com/questions/49330725/wrapperofnscoding-fails-with-single-value

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!