iOS 12.0 替代使用已弃用的 archiveRootObject:toFile:

Posted

技术标签:

【中文标题】iOS 12.0 替代使用已弃用的 archiveRootObject:toFile:【英文标题】:iOS 12.0 Alternative to Using Deprecated archiveRootObject:toFile: 【发布时间】:2019-05-03 22:47:12 【问题描述】:

ios 12 中,archiveRootObject:toFile: 已被弃用。任何人都可以提出一种简化的替代方案来将对象归档到文件中吗?

//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】:

感谢@vadian 的提示,这是我想出的在 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];

【讨论】:

您(或其他任何人)是否设法通过 requiresSecureCoding:YES 来实现这一点? 这里,如果您在 NSString 格式中保存数据,请使用 [NSString 类],或者如果您在 NSDictionary 格式中保存数据,请在 unarchivedObjectOfClass 中使用 [NSDictionary 类]:【参考方案2】:

unArchivedObjectOfClass 在尝试解码未使用安全编码的对象时向我抛出了错误。经过多次试验和错误,这终于在没有触发 iOS 12/13 弃用警告的情况下奏效了:

// 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];

【讨论】:

【参考方案3】:

作为suggested by Apple,我们应该使用FileManager来读取/写入归档文件。

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

【讨论】:

【参考方案4】:

替换为archivedDataWithRootObject:requiringSecureCoding:error:

+ (NSData *)archivedDataWithRootObject:(id)object 
             requiringSecureCoding:(BOOL)requiresSecureCoding 
                             error:(NSError * _Nullable *)error;

加上一个额外的步骤将数据写入磁盘。

请看Foundation iOS 11.4 to 12.0 API Differences

【讨论】:

以上是关于iOS 12.0 替代使用已弃用的 archiveRootObject:toFile:的主要内容,如果未能解决你的问题,请参考以下文章

已弃用的 AudioManger.setStreamMute 的替代方案?

已弃用的 google plus api 的替代解决方案是啥?

是否有快速替代已弃用的“SKPaymentTransaction.transactionReceipt”?

如何为已弃用的英特尔 IPP API 找到替代 API?

BitmapDrawable 已弃用的替代方案

替代已弃用的 AudioManager.isWiredHeadsetOn?