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];
}
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];
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];
As suggested by Apple, we should use FileManager for read/write the archived file.
func archiveURL() -> URL? {
guard let documentURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first
else { return nil }
return documentURL.appendingPathComponent("MyArchive.data")
}
func archive(customObject: CustomObject) {
guard let dataToBeArchived = try? NSKeyedArchiver.archivedData(withRootObject: customObject, requiringSecureCoding: true),
let archiveURL = archiveURL()
else {
return
}
try? dataToBeArchived.write(to: archiveURL)
}
func unarchive() -> CustomObject? {
guard let archiveURL = archiveURL(),
let archivedData = try? Data(contentsOf: archiveURL),
let customObject = (try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(archivedData)) as? CustomObject
else {
return nil
}
return customObject
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With