objective-cdeprecatednskeyedarchivernskeyedunarchivermacos-mojave

How to archive an array of NSSortDescriptor in Mojave


I had code that was working through High Sierra (10.13), that was successfully archiving and unarchiving an array of sort descriptors to NSData, but the operative calls have now been deprecated in Mojave (10.14). This is the code that worked:

NSArray<NSSortDescriptor*> *sortSettings = @[[NSSortDescriptor sortDescriptorWithKey:@"title" ascending:NO]];

NSData *sortData = [NSKeyedArchiver archivedDataWithRootObject:sortSettings];
NSArray<NSSortDescriptor*> *unarchivedSettings = [NSKeyedUnarchiver unarchiveObjectWithData:sortData];

// Test case passes
XCTAssertEqualObjects(unarchivedSettings.firstObject.key, @"title");

I've tried using the code below, with the calls suggested by the deprecation warnings, but it doesn't work.

NSArray<NSSortDescriptor*> *sortSettings = @[[NSSortDescriptor sortDescriptorWithKey:@"title" ascending:NO]];

NSError *archiveError = nil;
NSData *sortData = [NSKeyedArchiver archivedDataWithRootObject:sortSettings
                                         requiringSecureCoding:YES
                                                         error:&archiveError];
// Test cases pass
XCTAssertNotNil(sortData);
XCTAssertNil(archiveError);

NSError *unarchiveError = nil;
NSArray<NSSortDescriptor*> *unarchivedSettings = [NSKeyedUnarchiver unarchivedObjectOfClass:[NSArray class]
                                                                                   fromData:sortData
                                                                                      error:&unarchiveError];
XCTAssertNotNil(unarchivedSettings); // Fails
XCTAssertNil(unarchiveError); // Fails, with error below

Archival succeeds, returning an NSData, but the unarchive call returns an error:

Error Domain=NSCocoaErrorDomain Code=4864 "value for key 'NS.objects' was of unexpected class 'NSSortDescriptor'. Allowed classes are '{( NSArray )}'." UserInfo={NSDebugDescription=value for key 'NS.objects' was of unexpected class 'NSSortDescriptor'. Allowed classes are '{( NSArray )}'.}


Solution

  • You need to list all of the classes that are being archived (in this case, NSArray and NSSortDescriptor):

    [NSKeyedUnarchiver unarchivedObjectOfClasses:[NSSet setWithArray:@[
                                                  [NSArray class],
                                                  [NSSortDescriptor class]
                                                 ]]
                                        fromData:sortData
                                           error:&unarchiveError];