How to Nskeyedunarchiver.Unarchiveobject

How to NSKeyedUnarchiver.unarchiveObject

The usage of the new API to archive an array is a bit tricky.

You could have figured it out yourself if you wouldn't ignore the errors with try? /p>

To be able to decode an array of a custom class with unarchivedObject(ofClass:from: you have to use the plural form unarchivedObject(ofClasses:from: and specify both NSArray(!) and the custom class. Further your class must adopt NSSecureCoding

class Record : NSObject, NSSecureCoding {

static var supportsSecureCoding: Bool {
return true
}

....

do {
let archived = try NSKeyedArchiver.archivedData(withRootObject: [defaultRecord], requiringSecureCoding: false)

let records = try NSKeyedUnarchiver.unarchivedObject(ofClasses: [NSArray.self, Record.self], from: archived) as! [Record]
print(records)
} catch { print(error) }

But why do you archive defaultRecord as array at all? If you archive the single object you can leave your class as it is and write

do {
let archived = try NSKeyedArchiver.archivedData(withRootObject: defaultRecord, requiringSecureCoding: false)

let record = try NSKeyedUnarchiver.unarchivedObject(ofClass: Record.self, from: archived)
let records = [record]
print(records)
} catch { print(error) }

Side note: Consider to serialize the class with Codable. It's swiftier and doesn't require inheritance from NSObject.

How to deal with deprecated function 'unarchiveObject(with:)'?

You can do this in following way...

let result = jsonDict["result"] as? NSDictionary ?? [:]
let data = try! NSKeyedArchiver.archivedData(withRootObject: result, requiringSecureCoding: false)
UserDefaults.standard.set(data, forKey: "currentUser")

// Get data from Userdefault

let result = UserDefaults.standard.data(forKey: "currentUser")
if result != nil{
let dict = try! NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(result!) as? NSDictionary ?? [:]
print("Current User Details : - \(dict)")
}

Unarchive Array with NSKeyedUnarchiver unarchivedObject(ofClass:from:)

You can use unarchiveTopLevelObjectWithData(_:) to unarchive the data archived by archivedData(withRootObject:requiringSecureCoding:). (I believe this is not deprecated yet.)

But before showing some code, you should better:

  • Avoid using NSData, use Data instead

  • Avoid using try? which disposes error info useful for debugging

  • Remove all unneeded casts


Try this:

private static func archiveWidgetDataArray(widgetDataArray : [WidgetData]) -> Data {
do {
let data = try NSKeyedArchiver.archivedData(withRootObject: widgetDataArray, requiringSecureCoding: false)

return data
} catch {
fatalError("Can't encode data: \(error)")
}

}

static func loadWidgetDataArray() -> [WidgetData]? {
guard
isKeyPresentInUserDefaults(key: USER_DEFAULTS_KEY_WIDGET_DATA), //<- Do you really need this line?
let unarchivedObject = UserDefaults.standard.data(forKey: USER_DEFAULTS_KEY_WIDGET_DATA)
else {
return nil
}
do {
guard let array = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(unarchivedObject) as? [WidgetData] else {
fatalError("loadWidgetDataArray - Can't get Array")
}
return array
} catch {
fatalError("loadWidgetDataArray - Can't encode data: \(error)")
}
}

But if you are making a new app, you should better consider using Codable.

NSKeyedUnarchiver returning nil when retrieving custom class

You can use this method to unarchive the data.
https://developer.apple.com/documentation/foundation/nskeyedunarchiver/2963379-unarchivedobject

NSKeyedUnarchiver.unarchivedObject(ofClasses:from:)

You can write your unarchiving code as;

let data = try Data(contentsOf: filePath)
let object = try NSKeyedUnarchiver.unarchivedObject(ofClasses:[object.self, UIImage.self], from: data)

Hopefully, it works.

PS. One tip about naming classes. They should always start with capital letter.

EDIT: You should add UIImage.self also when trying to unarchive.
and you should change your archive method as seen below.

NSKeyedArchiver.archivedData(withRootObject: data, requiringSecureCoding: true)

Your model should also satisfy NSSecureCoding protocol when using this unarchive method.

extension object : NSSecureCoding {
static var supportsSecureCoding: Bool {
return true
}
}


Related Topics



Leave a reply



Submit