【问题标题】:WrapperOfNSCoding fails with single valueWrapperOfNSCoding 因单个值而失败
【发布时间】:2018-03-16 23:14:48
【问题描述】:

来自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)

错误是

致命错误:“试试!”表达式意外引发错误: Swift.EncodingError.invalidValue(WrapperOfNSCoding #1...

成功了

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

为什么会这样

【问题讨论】:

    标签: swift codable


    【解决方案1】:

    JSONEncoder 需要在顶层有效的 JSON 上下文,可以是 [:](字典)或 [](数组),您可以在其中放置一个元素,如本例中的 string

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

    JSONEncoder().encode([w]) 的情况下,对象创建了一个数组,每个元素都有一个字符串,在你的情况下是NSCoding

    另一方面,w 数据是一个字符串,[w] 是一个数组,每个索引都有一个字符串,因此JSONEncoder 不会给你一个错误 [w] 并给你一个错误 @987654336 @。

    【讨论】:

      猜你喜欢
      • 2017-11-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-06
      • 1970-01-01
      • 2018-02-16
      • 1970-01-01
      相关资源
      最近更新 更多