Since upgrading to Swift 4.2 I've found that many of the NSKeyedUnarchiver and NSKeyedArchiver methods have been deprecated and we must now use the type method static func unarchivedObject<DecodedObjectType>(ofClass: DecodedObjectType.Type, from: Data) -> DecodedObjectType?
to unarchive data.
I have managed to successfully archive an Array of my bespoke class WidgetData, which is an NSObject subclass:
private static func archiveWidgetDataArray(widgetDataArray : [WidgetData]) -> NSData {
guard let data = try? NSKeyedArchiver.archivedData(withRootObject: widgetDataArray as Array, requiringSecureCoding: false) as NSData
else { fatalError("Can't encode data") }
return data
}
The problem comes when I try to unarchive this data:
static func loadWidgetDataArray() -> [WidgetData]? {
if isKeyPresentInUserDefaults(key: USER_DEFAULTS_KEY_WIDGET_DATA) {
if let unarchivedObject = UserDefaults.standard.object(forKey: USER_DEFAULTS_KEY_WIDGET_DATA) as? Data {
//THIS FUNCTION HAS NOW BEEN DEPRECATED:
//return NSKeyedUnarchiver.unarchiveObject(with: unarchivedObject as Data) as? [WidgetData]
guard let nsArray = try? NSKeyedUnarchiver.unarchivedObject(ofClass: NSArray.self, from: unarchivedObject as Data) else {
fatalError("loadWidgetDataArray - Can't encode data")
}
guard let array = nsArray as? Array<WidgetData> else {
fatalError("loadWidgetDataArray - Can't get Array")
}
return array
}
}
return nil
}
But this fails, as using Array.self
instead of NSArray.self
is disallowed. What am I doing wrong and how can I fix this to unarchive my Array?
You can use
unarchiveTopLevelObjectWithData(_:)
to unarchive the data archived byarchivedData(withRootObject:requiringSecureCoding:)
. (I believe this is not deprecated yet.)But before showing some code, you should better:
Avoid using
NSData
, useData
insteadAvoid using
try?
which disposes error info useful for debuggingRemove all unneeded casts
Try this:
But if you are making a new app, you should better consider using
Codable
.// Achieving data
This is the way I have updated my code and its working for me
is deprecated as well. So to unarchive data without secure coding you need to:
NSKeyedUnarchiver
withinit(forReadingFrom: Data)
requiresSecureCoding
of created unarchiver to false.decodeObject(of: [AnyClass]?, forKey: String) -> Any?
to get your object, just use proper class andNSKeyedArchiveRootObjectKey
as key.You are likely looking for this: