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

时间:2019-09-10 20:35:42

标签: swift codable nscoding nskeyedarchiver nskeyedunarchiver

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

  

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

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

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

我的产品类以@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:

enter image description here

“崩溃”标签下Xcode Organizer的屏幕截图:

enter image description here

在代码中导致以下一行:

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

enter image description here

带有@Objc批注的产品类。

enter image description here

1 个答案:

答案 0 :(得分:3)

似乎您正在混用CodableNSCoding。不要尝试同时使用两者。 NSKeyedUnarchiver属于NSCoding

您的类包含符合属性列表的属性。删除NSCoding并仅使用Codable。 (通过这种方式,建议以单数形式Product命名该类。)

删除与NSCoding相关的所有内容,包括协议一致性,并删除与Codable的类,不必使类必须从NSObject继承(该对象甚至可以是一个结构)。 / p>

loadProducts函数可以简化为

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

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

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