问题
With iOS 12, archiveRootObject:toFile:has been deprecated. Can anyone suggest a streamlined alternative to archiving objects to a file?
//Generic example of archiver prior to iOS 12.0
-(BOOL) archive:(id)archiveObject withFileName:(NSString*)filename
{
NSString *path = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"];
return [NSKeyedArchiver archiveRootObject:archiveObject toFile:path];
}
回答1:
Thanks to @vadian for the hint, here's what I've come up with to do archiving and unarchiving under iOS 12:
NSError *error = nil;
NSString *docsDir;
NSArray *dirPaths;
//Get the device's data directory:
dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = [dirPaths objectAtIndex:0];
NSString *databasePath = [[NSString alloc] initWithString: [docsDir stringByAppendingPathComponent:@"appData.data"]];
//Archive using iOS 12 compliant coding:
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:@"foo" requiringSecureCoding:NO error:&error];
[data writeToFile:databasePath options:NSDataWritingAtomic error:&error];
NSLog(@"Write returned error: %@", [error localizedDescription]);
//Unarchive the data:
NSData *newData = [NSData dataWithContentsOfFile:databasePath];
NSString *fooString = [NSKeyedUnarchiver unarchivedObjectOfClass:[NSString class] fromData:newData error:&error];
回答2:
As suggested by Apple, we should use FileManager for read/write the archived file.
guard let documentURL = FileManager().urls(for: .documentDirectory, in: .userDomainMask).first else { return }
let filePath = "MyArchive.data"
let fileURL = documentURL.appendingPathComponent(filePath)
// Archive
if let dataToBeArchived = try? NSKeyedArchiver.archivedData(withRootObject: myObject, requiringSecureCoding: true) {
try? dataToBeArchived.write(to: fileURL)
}
// Unarchive
if let archivedData = try? Data(contentsOf: fileURL),
let myObject = (try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(archivedData)) as? Object {
/// Do anything with the unarchived object
///
///
}
回答3:
The replacement is archivedDataWithRootObject:requiringSecureCoding:error:
+ (NSData *)archivedDataWithRootObject:(id)object
requiringSecureCoding:(BOOL)requiresSecureCoding
error:(NSError * _Nullable *)error;
plus an extra step to write the data to disk.
Please see Foundation iOS 11.4 to 12.0 API Differences
回答4:
unArchivedObjectOfClass threw an error for me when trying to decode an object that didn't use secure encoding. After much trial and error, this is what finally worked without triggering an iOS 12/13 deprecation warning:
// Archive the object
NSData* data = [NSKeyedArchiver archivedDataWithRootObject:theObject requiringSecureCoding:NO error:nil];
// Unarchive the object
NSKeyedUnarchiver* unarchiver = [[NSKeyedUnarchiver alloc] initForReadingFromData:data error:nil];
unarchiver.requiresSecureCoding = NO;
id theCopy = [unarchiver decodeTopLevelObjectForKey:NSKeyedArchiveRootObjectKey error:nil];
来源:https://stackoverflow.com/questions/53580240/ios-12-0-alternative-to-using-deprecated-archiverootobjecttofile