I’m attempting to use NSKeyedArchiver in a ValueTransformer for SwiftData / Core Data.
I’m getting an error using NSKeyedUnarchiver.unarchivedObject(ofClass:
on an NSArray
filled with NSMeasurement
s:
func testEncode() throws {
//let original: NSArray = ["Strings", "work", "fine"]
let original: NSArray = [NSMeasurement(doubleValue: 42, unit: UnitMass.grams)]
let data = try NSKeyedArchiver.archivedData(withRootObject: original, requiringSecureCoding: true)
let nsArray = try NSKeyedUnarchiver.unarchivedObject(ofClass: NSArray.self, from: data)
XCTAssertEqual(original, nsArray)
}
“Error Domain=NSCocoaErrorDomain Code=4864 “value for key ‘NS.objects’ was of unexpected class ‘NSMeasurement’
Allowed classes are:
{(
“‘NSArray'”
)}
Answers on a similar question point to using NSCoder
and its methods decodeArrayOfObjects(ofClass:forKey:)
or decodeArrayOfObjects(ofClasses:forKey:)
.
However, I want to know why this does not work on the NSKeyedArchiver
static method.
Is there any way to decode the array properly using the NSKeyedArchiver
static unarchivedObject(ofClass:
rather than the NSCoder
instance methods?
You need to use NSKeyedUnarchiver
unarchivedObject(ofClasses:from:)
instead, even for a one-object-type array.
Use ofClasses:
plural rather than ofClass:
singular.
Pass the type of the collection itself plus the object type(s) inside the array.
func testEncode() throws {
let original: NSArray = [NSMeasurement(doubleValue: 42, unit: UnitMass.grams)]
let data = try NSKeyedArchiver.archivedData(withRootObject: original, requiringSecureCoding: true)
// Using only `NSArray.self` does not work
//let nsArray = try NSKeyedUnarchiver.unarchivedObject(ofClass: NSArray.self, from: data)
// Use [NSArray.self, NSMeasurement.self] instead
let nsArrayAny: Any? = try NSKeyedUnarchiver.unarchivedObject(ofClasses: [NSArray.self, NSMeasurement.self], from: data)
let nsArray = nsArrayAny as! NSArray
XCTAssertEqual(original, nsArray)
}
You need to pass both the collection type and the object types it contains. Omitting the array type results in the error
Error Domain=NSCocoaErrorDomain Code=4864 “value for key ‘root’ was of unexpected class ‘NSArray’ Allowed classes are: {( ‘NSMeasurement’ )}