I'm converting a codebase from using NSCoding
to using Codable
. I have run into an issue when trying to restore data encoded with NSCoding
. I have an object that was encoded with the code:
let encodedUser = NSKeyedArchiver.archivedData(withRootObject: user)
let userDefaults = UserDefaults.standard
userDefaults.set(encodedUser, forKey: userKey)
userDefaults.synchronize()
It was previously being decoded with the code:
if let encodedUser = UserDefaults.standard.data(forKey: userKey) {
if let user = NSKeyedUnarchiver.unarchiveObject(with: encodedUser) as? User {
\\ do stuff
}
}
After updating the User
object to be Codable
, I attempted to update the archive/unarchive code to use PropertyListDecoder
because I saw that archivedData(withRootObject:)
returns data formatted as NSPropertyListBinaryFormat_v1_0
. When running this code:
if let encodedUser = UserDefaults.standard.data(forKey: userKey) {
let user = try! PropertyListDecoder().decode(User.self, from: encodedUser)
\\ do stuff
}
I get a keyNotFound
error for the first key I'm looking for, and breakpointing in my init(from: Decoder)
, I can see that the container has no keys. I also tried to use PropertyListSerialization.propertyList(from:options:format)
to see if I could pass that result into PropertyListDecoder
, but that function gave me an NSCFDictionary
, which is structured in a really strange way but does appear to contain all the data I'm looking for.
So is it possible to decode an object using Codable
APIs if it was encoded with NSKeyedArchiver.archivedData(withRootObject:)
? How can I achieve this?
I decided that the answer is almost certainly no, you cannot use Codable
to decode what NSCoding
encoded. I wanted to get rid of all the NSCoding
cruft in my codebase, and settled on a migration path where I have both protocols implemented in the critical data models to convert stored data from NSCoding
to Codable
formats, and I will remove NSCoding in the future when enough of my users have updated.