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】:您似乎混淆了Codable
和NSCoding
。不要试图同时使用两者。 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() 取消归档旧对象