You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用PropertyList编解码时为何出现“Expected to decode Data but found an array instead”错误?

问题分析与解决方案

这个错误的核心原因是你编码的是可选类型的Data(Data?),但解码时却尝试解析为非可选的Data,而PropertyListEncoder对可选Data的编码行为,导致最终存储的是数组结构,和你期望的Data类型不匹配。

具体细节

你在encode(to:)方法中直接传入了UIImagePNGRepresentation(image)的返回值——这是一个Data?类型。PropertyListEncoder在处理可选Data时,会将其编码为属性列表中的数组格式(底层是把NSOptional包装的NSData序列化为字节数组)。而你解码时调用container.decode(Data.self, forKey: .image),期望得到一个Data类型,但实际读取到的是数组,因此触发类型不匹配错误。

修复方案

你需要确保编码的是非可选的Data,先对UIImagePNGRepresentation的结果进行解包验证,再执行编码:

修改你的encode(to:)方法:

func encode(to encoder: Encoder) throws {
    var container = encoder.container(keyedBy: CodingKeys.self)
    try container.encode(rect, forKey: .rect)
    
    // 先验证并解包PNG数据,避免编码可选类型
    guard let pngData = UIImagePNGRepresentation(image) else {
        throw EncodingError.invalidValue(
            image,
            EncodingError.Context(
                codingPath: [CodingKeys.image],
                debugDescription: "无法将UIImage转换为PNG格式数据"
            )
        )
    }
    try container.encode(pngData, forKey: .image)
}

这样修改后,你编码的是确定存在的Data类型,PropertyListEncoder会将其正确序列化为属性列表中的NSData对应格式,解码时就能正常解析为Data,进而转换成UIImage。

另外,建议你在解码时也去掉强制解包!,改用安全的可选绑定,避免因数据损坏导致崩溃:

init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)
    rect = try container.decode(CGRect.self, forKey: .rect)
    
    let imageData = try container.decode(Data.self, forKey: .image)
    guard let decodedImage = UIImage(data: imageData) else {
        throw DecodingError.dataCorrupted(
            DecodingError.Context(
                codingPath: [CodingKeys.image],
                debugDescription: "无法将解码后的数据转换为UIImage"
            )
        )
    }
    image = decodedImage
}

这样你的编解码流程会更健壮,同时彻底解决类型不匹配的问题。

内容的提问来源于stack exchange,提问作者Sweeper

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:31:49