Nskeyedunarchiver Fails to Decode a Custom Object in Swift

NSKeyedUnarchiver fails to decode a custom object in swift

As Martin pointed out the in the comments, the code works fine in a compiled app, so it's definitely a playground bug.

David, in the comments, suggested to use @objc(User) in order to get a non-mangled class name, but it didn't help in this specific case, so - as of beta 2 - I still haven't find a workaround to make it work in the playground.

Can't unarchive custom Object with NSKeyedUnarchiver in AR Multiuser

Since here you use Codable

struct ARUser: Codable {

Then

do {
let dataToObject = try JSONDecoder().decode(ARUser.self,from:data)
let objectToData = try JSONEncoder().encode(dataToObject)
}
catch {
print(error)
}

NSKeyedUnarchiver is an old Objective-C stuff

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

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.

Can't cast Data from NSKeyedUnarchiver to Object

your error is here:

    coder.encode(firstName, forKey: "fisrtName")

typo -> firstName

Swift NSCoding issue with single custom object

The issue was with the guard statments stopping the initialization of the object being unarchived. I changed from guard statements to let statements assigning an empty string if it couldn't decode the value as Michael suggested in the comments above. This helped me find the value that had an improper key so I could update the code. All is well now.

Cannot archive custom class object with NSKeyedArchiver

The NSKeyedArchiver.archivedData(withRootObject:) method should be used on objects that conform to NSCoding NOT Codable/Encodable/Decodable.

If you want your object to implement the Codable protocol you can use the JSONEncoder and JSONDecoder like below to achieve the same thing:

let car = Car(name: "Ferrari")
if let encodedCarData: Data = try? JSONEncoder().encode(car) {
let decodedCar = try? JSONDecoder().decode(Car.self, from: encodedCarData)
}

If you wish to use the NSKeyedArchiver instead, you can use the example below:

class Car: NSObject, NSSecureCoding {

static var supportsSecureCoding: Bool { return true }

var name: String

init(name: String) {
self.name = name
}

required init?(coder aDecoder: NSCoder) {
guard let name = aDecoder.decodeObject(forKey: "name") as? String else { return nil }
self.name = name
}

func encode(with aCoder: NSCoder) {
aCoder.encode(name, forKey: "name")
}

}

let car = Car(name: "Ferrari")
if let encodedCarData =
try? NSKeyedArchiver.archivedData(withRootObject: car,
requiringSecureCoding: false) {
let decodedCar =
try NSKeyedUnarchiver.unarchivedObject(ofClass: Car.self,
from: encodedCarData)
}

You should also note, archivedData(withRootObject:) was deprecated in iOS 12.0 and you should use +archivedDataWithRootObject:requiringSecureCoding:error: instead.



Related Topics



Leave a reply



Submit