My app uses a custom class as its data model:
class Drug: NSObject, NSCoding {
// Properties, methods etc...
}
I have just created a Today extension and need to access the user’s data from it, so I use NSCoding to persist my data in both the app container and the shared container. These are the save and load functions in the main app:
func saveDrugs() {
// Save to app container
let isSuccessfulSave = NSKeyedArchiver.archiveRootObject(drugs, toFile: Drug.ArchiveURL.path)
if isSuccessfulSave {
print("Drugs successfully saved locally")
} else {
print("Error saving drugs locally")
}
// Save to shared container for extension
let isSuccessfulSaveToSharedContainer = NSKeyedArchiver.archiveRootObject(drugs, toFile: Drug.SharedArchiveURL.path)
if isSuccessfulSaveToSharedContainer {
print("Drugs successfully saved to shared container")
} else {
print("Error saving drugs to shared container")
}
}
func loadDrugs() -> [Drug]? {
return NSKeyedUnarchiver.unarchiveObject(withFile: Drug.ArchiveURL.path) as? [Drug]
}
I encountered the problem of class namespacing where the NSKeyedUnarchiver in my Today extension could not decode the object properly, so I used this answer and added @objc
before the class definition:
@objc(Drug)
class Drug: NSObject, NSCoding {
// Properties, methods etc...
}
This solved the problem perfectly. However, this will be version 1.3 of my app, and it seems this breaks the unarchiving process for pre-existing data (as I thought it might).
What is the best way to handle this scenario, as if I just make this change, the new version of the app will crash for existing users!
I cannot find any other answers about this, and I am not sure that the NSKeyedArchiver.setClass()
method is relevant, nor am I sure where to use it.
Any help would be gratefully received. Thanks.