Reputation: 91
I'm trying to decode an array of URL objects using NSKeyedUnarchiver. Here is the code:
let urlArray: [URL] = [URL(string: "https://apple.com")!,
URL(string: "https://google.com")!]
do {
let archivedUrls = try NSKeyedArchiver.archivedData(withRootObject: urlArray, requiringSecureCoding: false)
let _ = try NSKeyedUnarchiver.unarchivedObject(ofClass: NSArray.self, from: archivedUrls)
} catch {
print(error)
}
I get the following error:
Error Domain=NSCocoaErrorDomain Code=4864 "value for key 'NS.objects' was of unexpected class 'NSURL'. Allowed classes are '{(
NSArray
)}'." UserInfo={NSDebugDescription=value for key 'NS.objects' was of unexpected class 'NSURL'. Allowed classes are '{(
NSArray
)}'.}
If I replace let _ = try NSKeyedUnarchiver.unarchivedObject(ofClass: NSArray.self, from: archivedUrls)
by let _ = try NSKeyedUnarchiver.unarchivedObject(ofClasses: [NSArray.self, NSURL.self], from: archivedUrls)
, then it works. But that means it can decode either an NSArray
or NSURL
object, not an NSArray
containing NSURL
objects.
If I change the array to be an array of String
instead, everything works fine:
let stringArray: [String] = ["string", "string2"]
do {
let archivedStrings = try NSKeyedArchiver.archivedData(withRootObject: stringArray, requiringSecureCoding: false)
let _ = try NSKeyedUnarchiver.unarchivedObject(ofClass: NSArray.self, from: archivedStrings)
} catch {
print(error)
}
Does anyone have an explanation for that behaviour?
Upvotes: 2
Views: 556
Reputation: 47896
If you do not require Secure Coding (requiringSecureCoding: false
), you can use unarchiveTopLevelObjectWithData(_:)
.
do {
let archivedUrls = try NSKeyedArchiver.archivedData(withRootObject: urlArray, requiringSecureCoding: false)
if let urls = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(archivedUrls) as? [URL] {
print(urls)
} else {
print("not URLs")
}
} catch {
print(error)
}
Or you can specify the types included in the archive using unarchivedObject(ofClasses:from:)
.
do {
let archivedUrls = try NSKeyedArchiver.archivedData(withRootObject: urlArray, requiringSecureCoding: true)
if let urls = try NSKeyedUnarchiver.unarchivedObject(ofClasses: [NSArray.self, NSURL.self], from: archivedUrls) as? [URL] {
print(urls)
} else {
print("not URLs")
}
} catch {
print(error)
}
NSString
seems to be an exception for this rule.
Upvotes: 1