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

NSKeyedUnarchiver decodeObjectForKey: cannot decode object of class for key (NS.objects)

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

Fatal Exception: NSInvalidUnarchiveOperationException *** -[NSKeyedUnarchiver decodeObjectForKey:]: cannot decode object of class (App_Title.Products) for key (NS.objects); the class may be defined in source code or a library that is not linked

我在#unarchiveObject:

之前已经做了 NSKeyedUnarchiver.setClass
func loadProducts() -> [Products]? {
    NSKeyedUnarchiver.setClass(Products.self, forClassName: "Products")
    let unarchivedData = NSKeyedUnarchiver.unarchiveObject(withFile: Products.ArchiveURL.path)

我的产品 class 以 @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 管理器的屏幕截图:

这导致代码中的这一行:

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

带有@Objc 注释的产品class。

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

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

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

loadProducts函数可以简化为

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

thrown 错误移交给调用者是个好习惯

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