Unarchive Array with Nskeyedunarchiver Unarchivedobject(Ofclass:From:)

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.

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.

Archive and Unarchive an array of UIColours to NSUserDefaults in iOS 12?

You can use unarchiveTopLevelObjectWithData(_:):

func loadColours() -> [UIColor]? {
guard let unarchivedObject = UserDefaults.standard.data(forKey: "faveColours") else {
return nil
}

do {
guard let array = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(unarchivedObject) as? [UIColor] else {
fatalError("Can't load colours.")
}
return array
} catch {
fatalError("Can't load colours.")
}

}

archivedObject(ofClass:from:) treats [SCNNode] differently that SCNNode

The modern way to decode an array of SCNNode is by saying

let components = try? NSKeyedUnarchiver.unarchivedArrayOfObjects(ofClass: SCNNode.self, from: moleData)

That should work. If it doesn't, you'll have to just keep using the deprecated method; but I think it will.

NSKeyedUnarchiver changes in iOS12 - How to unarchive an Array of Strings

Finally I found out myself.
It worked with this method:

if let fileNames = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(dataObject) as? Array<String> {
// ...
}


Related Topics



Leave a reply



Submit