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

[亡魂溺海] 提交于 2021-02-10 07:06:57

问题


I looked through whole SO but still no answer. My app reports this problem:

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

I did already do NSKeyedUnarchiver.setClass just before #unarchiveObject:

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

My Products class begins with @Objc:

import Foundation

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

Adding the two lines above which seemed to help people didn't bring me any luck. Before them and after them it's the same behaviour. I personally could never reproduce this issue myself.

During development I keep very closely to the app guide on peristance and reviewed it multiple times.

Just before NSKeyedArchiver I check for file existance:

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

Here some additional informations in screenshots.

The only place where I could find a real exception description was Firebase Crashalytics:

A screenshot from the Xcode Organizer under the Crash tab:

Which leads to this line in the code:

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

Products class with @Objc annotation.


回答1:


It seems that you are mixing up Codable and NSCoding. Don't try to use both simultaneously. NSKeyedUnarchiver belongs to NSCoding.

Your class contains property list compliant properties. Drop NSCoding and use only Codable. (By the way it's recommended to name the class in singular form Product).

Delete everything which is related to NSCoding including the protocol conformance and with Codable it's not necessary that the class must inherit from NSObject (the object can be even a struct).

The loadProducts function can be reduced to

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

It's good practice to hand over thrown errors to the caller

And delete the CodingKeys, you don't need them if the keys match the property names.



来源:https://stackoverflow.com/questions/57877912/nskeyedunarchiver-decodeobjectforkey-cannot-decode-object-of-class-for-key-ns

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!