NSKeyedUnarchiver decodeObjectForKey:无法解码类对象的键(NS.objects)

Posted

技术标签:

【中文标题】NSKeyedUnarchiver decodeObjectForKey:无法解码类对象的键(NS.objects)【英文标题】:NSKeyedUnarchiver decodeObjectForKey: cannot decode object of class for key (NS.objects) 【发布时间】:2020-01-12 15:09:19 【问题描述】:

我浏览了整个 SO,但仍然没有答案。我的应用报告了这个问题:

致命异常:NSInvalidUnarchiveOperationException *** -[NSKeyedUnarchiver decodeObjectForKey:]:无法解码类(App_Title.Products)的对象的键(NS.objects);这 类可以定义在源代码或未链接的库中

我在#unarchiveObject 之前已经做了 NSKeyedUnarchiver.setClass:

func loadProducts() -> [Products]? 
    NSKeyedUnarchiver.setClass(Products.self, forClassName: "Products")
    let unarchivedData = NSKeyedUnarchiver.unarchiveObject(withFile: Products.ArchiveURL.path)

我的 Products 类以 @Objc 开头:

import Foundation

@objc(Products)
class Products: NSObject, Codable, NSCoding  ... 

添加上面似乎对人们有所帮助的两行并没有给我带来任何运气。在他们之前和之后,这是相同的行为。我个人永远无法自己重现此问题。

在开发过程中,我密切关注peristance 上的应用指南,并多次查看。

就在 NSKeyedArchiver 之前,我检查文件是否存在:

let filePath = Products.ArchiveURL.path
let fileManager = FileManager.default
if fileManager.fileExists(atPath: filePath) 

这里是屏幕截图中的一些附加信息。

我能找到真正异常描述的唯一地方是 Firebase Crashalytics:

来自 Xcode Organizer 的 Crash 选项卡下的屏幕截图:

这导致代码中的这一行:

NSKeyedUnarchiver.setClass(Products.self, forClassName: "Products")
let unarchivedData = NSKeyedUnarchiver.unarchiveObject(withFile: Products.ArchiveURL.path)

带有@Objc 注释的产品类。

【问题讨论】:

【参考方案1】:

您似乎混淆了CodableNSCoding。不要试图同时使用两者。 NSKeyedUnarchiver 属于 NSCoding

您的类包含符合属性列表的属性。删除 NSCoding 并仅使用 Codable。 (顺便说一下,建议将类命名为单数形式Product)。

删除与NSCoding 相关的所有内容,包括协议一致性,对于Codable,类不必继承自NSObject(对象甚至可以是结构)。

loadProducts 函数可以简化为

func loadProducts() throws -> [Product] 
    let data = try Data(contentsOf: Product.ArchiveURL)
    return try PropertyListDecoder().decode([Product].self, from: data)

最好将thrown 错误交给调用者

并删除CodingKeys,如果键与属性名称匹配,则不需要它们。

【讨论】:

是的,是的。这就是答案!精彩的解决方案@vadian。对于编码,我使用 PropertyListEncoder 并为我的旧 NSKeyedUnarchiver 对象实现了恢复过程。

以上是关于NSKeyedUnarchiver decodeObjectForKey:无法解码类对象的键(NS.objects)的主要内容,如果未能解决你的问题,请参考以下文章

NSKeyedUnarchiver.unarchiveObject 不工作 [重复]

NSKeyedUnarchiver.unarchiveObject() 取消归档旧对象

NSKeyedUnarchiver - 删除解码的数据?

NSKeyedUnarchiver - 需要尝试/捕获?

如何将代表与 NSKeyedUnarchiver 一起使用?

NSKeyedUnarchiver.unarchivedObject 为字典返回 nil