Search code examples
swiftnscodingnskeyedarchiver

UserDefaults Decoder Not Decoding


I have the following decoder code. It always executes the catch block. The error I get is as follows:

This decoder will only decode classes that adopt NSSecureCoding

if let dataToRetrieve = UserDefaults.standard.data(forKey: "currentPlayerToon") {
    do {
        let returnedPlayerInformation = try NSKeyedUnarchiver.unarchivedObject(ofClass: PlayerClass.self, from: dataToRetrieve)
        print("Success")
    } catch {
        print(error)
    }
}

Here is my save. This always succeeds.

do {
    let dataToSave = try NSKeyedArchiver.archivedData(withRootObject: cachedToonToSave, requiringSecureCoding: false)
    UserDefaults.standard.set(dataToSave, forKey: "currentPlayerToon")
    print("saving worked")
} catch {
    print("saving failed")
}

And here is the class declaration.

class PlayerClass: NSObject, NSCoding {
    
    
    var toonName : String

Solution

  • Apple wants everyone to use NSSecureCoding instead of just NSCoding. You need to change your class to conform to NSSecureCoding. Then you pass true to the requiringSecureCoding parameter when you create the archive.

    // Change NSCoding to NSSecureCoding
    class PlayerClass: NSObject, NSSecureCoding {
        // The following is needed as well
        static var supportsSecureCoding: Bool { return true }
    
        var toonName : String
        var toonLevel : Float
    
        // and the rest as you already have it
    

    and:

    let dataToSave = try NSKeyedArchiver.archivedData(withRootObject: cachedToonToSave, requiringSecureCoding: true)
    

    With just those changes your code should work.

    You will need to resave the updated data in user defaults before you can load it back in.