skip to Main Content

iOS 16.4 deprecates unarchiveTopLevelObjectWithData(_:) and should be replaced with unarchivedObject(ofClass:from:).

When you archived a Swift Dictionary like [String: Any], how do you use the newer API to unarchive it?

NSKeyedUnarchiver.unarchivedObject(ofClass: [String: Any].self, from: data) results in a build time error:

Static method ‘unarchivedObject(ofClass:from:)’ requires that ‘[String : Any]’ conform to ‘NSCoding’

//create the data from dictionary
let dictionary: [String: Any] = ["Text": "Hello", "Number": 1, "Array": ["Hello", "World"]]
let data = try! NSKeyedArchiver.archivedData(withRootObject: dictionary, requiringSecureCoding: true)

//and later get the dictionary from the data
let dictionary = try? NSKeyedUnarchiver.unarchivedObject(ofClass: [String: Any].self, from: data) //sorry no can do

2

Answers


  1. Since the Swift dictionary of type [String: Any] doesn’t conform to NSCoding, you need to drop back to using NSDictionary. Since you are also using secure coding, you also need to list all types that can be in the dictionary.

    You will need to use the unarchivedObject(ofClasses:from:) method so you can list all of the classes.

    let dictionary = try? NSKeyedUnarchiver.unarchivedObject(ofClasses: [NSDictionary.self, NSArray.self], from: data) as? NSDictionary
    

    You may also end up needing to add NSString.self and NSNumber.self to the list of classes. Keep adding the classes that appear in the error message until it works.

    Login or Signup to reply.
  2. You can use this dummy object: [NSObject.self] instead of [NSDictionary.self, NSArray.self ...... ].
    With this, you cover all NS cases.
    It worked for me, although purple message appears (Apple always on the safe side. Not bad, but…

    -[NSKeyedUnarchiver validateAllowedClass:forKey:]: NSSecureCoding allowed classes list contains [NSObject class], which bypasses security by allowing any Objective-C class to be implicitly decoded. Consider reducing the scope of allowed classes during decoding by listing only the classes you expect to decode, or a more specific base class than NSObject. This will become an error in the future. Allowed class list: {(
    "’NSObject’ (0x219ef2d98) [/usr/lib]"
    )}

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search