iOS 12.0 Alternative to Using Deprecated archiveRootObject:toFile:

旧巷老猫 提交于 2020-12-29 05:24:27

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!