In a class, I call the following (edited to simplify, but it matches the real case).
If I do this:
func getData() -> someClass? {
_ = someURL.startAccessingSecurityScopedResource()
if let data = NSData(contentsOf: someURL as URL) {
do {
let unarchiver = try NSKeyedUnarchiver(forReadingFrom: data as Data)
print((unarchiver.decodeObject(of: [NSArray.self, someClass.self /* and few others*/], forKey: oneKey) as? someClass)?.aProperty)
if let result = unarchiver.decodeObject(of: [NSArray.self, someClass.self /* same other types*/], forKey: oneKey) as? someClass {
unarchiver.finishDecoding()
print("unarchived success")
return result
} else {
unarchiver.finishDecoding()
print("unarchiving failed")
return someClass()
}
}
catch {
return nil
}
}
I get a failure on log : unarchiving failed
But if I comment out the print(unarchiver.decodeObject) - line 8, it works and I get unarchived success
// print((unarchiver.decodeObject(of: [NSArray.self, someClass.self /* and few others*/], forKey: oneKey) as? someClass)?.aProperty)
However, when I do exactly the same for another class (I've compared line by line to be sure), it works even with the print statement.
What could be happening here ?
I’ve found that it’s quicker to resolve archiving issues when we share small working examples. To that end, I took the BorderModel and FrameModel classes from this post and wrote the following code to exercise archiving and unarchiving:
func main() throws {
let borderModel = BorderModel(showBorder: true)
let models = [FrameModel(count: 1), FrameModel(count: 2)]
let archiver = NSKeyedArchiver(requiringSecureCoding: true)
defer { archiver.finishEncoding() }
archiver.encode(borderModel, forKey: "borderModel")
archiver.encode(models as NSArray, forKey: "models")
let archive = archiver.encodedData
let unarchiver = try NSKeyedUnarchiver(forReadingFrom: archive)
defer { unarchiver.finishDecoding() }
assert(unarchiver.requiresSecureCoding)
guard
let borderModel2 = try unarchiver.decodeTopLevelObject(of: BorderModel.self, forKey: "borderModel"),
let m = try unarchiver.decodeTopLevelObject(of: [NSArray.self, FrameModel.self], forKey: "models"),
let models2 = m as? [FrameModel]
else {
throw POSIXError(.ENOTTY) // Need a better error (-:
}
print(borderModel2.showBorder) // true
print(models2.map { $0.count } ) // [1, 2]
}
try main()
I tested this with Xcode 26.2 on macOS 26.2 and it ran as expected. And I duplicate the guard statement, so that it decodes everything twice, it continues to work.
Please try this for yourself to confirm that it works. Then look at your code to see what it’s doing differently. And if you can’t figure it out, post a modified version of this snippet that shows the problem.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"