为什么 "Expected to decode Data but found an array instead" 我的代码中没有数组

Why "Expected to decode Data but found an array instead" I have no arrays in my code

我有这个可编码的结构:

struct Foo: Codable {
    let rect: CGRect
    let image: UIImage

    init(rect: CGRect, image: UIImage) {
        self.rect = rect
        self.image = image
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(rect, forKey: .rect)
        try container.encode(UIImagePNGRepresentation(image), forKey: .image)
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        rect = try container.decode(CGRect.self, forKey: .rect)
        image = try UIImage(data: container.decode(Data.self, forKey: .image))!
    }

    enum CodingKeys : CodingKey {
        case rect
        case image
    }
}

现在我创建一个 Foo 并尝试对其进行编码和解码:

let image = UIImage(named: "my_image")
let foo = Foo(rect: .zero, image: image!)
let encoder = PropertyListEncoder()
let data = try! encoder.encode(foo)
let decoder = PropertyListDecoder()
try! decoder.decode(Foo.self, from: data)

现在在decode行,出现这个错误:

Swift.DecodingError.typeMismatch(Foundation.Data, Swift.DecodingError.Context(codingPath: [__lldb_expr_244.Foo.CodingKeys.image], debugDescription: "Expected to decode Data but found an array instead.", underlyingError: nil))

显然,解码器在尝试解码图像数据时发现了一个数组。为什么会这样?似乎 Data 不知何故变成了一个数组。我很困惑因为

Data() is Codable

计算结果为真,因此编码人员理论上应该能够 en/decode 一个 Data。为什么会变成数组?

编辑:我正在使用 Xcode 9.1

这里是my_image:

我确定这是一个错误,问题似乎出在编码过程中,当编码 UIImagePNGRepresentation 数据时,返回为 Optional 事情真的出错了,如果您更改 encode 方法以强制这样的数据:

container.encode(UIImagePNGRepresentation(image)!, forKey: .image)

而不是:

container.encode(UIImagePNGRepresentation(image), forKey: .image)

在 Xcode 9.1 和 9.2 中都可以工作,如果你将数据保留为可选,编码将仅在 9.2 上工作而在 9.1 上失败,由于某种原因图像数据大小将加倍9.1.

我很确定 this bug report 在 swift.org

其中还提到它会导致内存使用量是数据大小的两倍,这是我在本地设置中看到的情况。

所以简单的解决方法是强制 UIImagePNGRepresentation(..) 数据或升级到 9.2,此错误已修复。

希望这能回答您的问题,确实是非常有趣的发现!