问题描述
仅提供一些背景信息。几年前,我失去了说话的能力,并且学会了如何专门编写代码以自己为语音应用创建良好的文本。令人惊讶的是,许多其他人发现它很有用。苹果每周报告约15,000次会话。顺便说一句是免费的。
在我开始学习时,目标C是当前的语言,所以这就是我所学的。我现在正在学习Swift,但还不准备重写我的应用程序。我只是还不够了解。
我正在尝试更新应用程序,但是NSKeyedArchiver有一个不推荐使用的方法,我一直在尝试修复它。以下是显示代码的代码片段。当用户关闭应用程序并应保存其数据时,此命令将运行:
...
persistence.field19 = [NSNumber numberWithBool:self.autoOn];
persistence.field20 = [NSNumber numberWithBool:self.instructionShown];
NSMutableData *data = [[NSMutableData alloc] init];
//NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initRequiringSecureCoding:false];
[archiver encodeObject:persistence
forKey:kDataKey];
[archiver finishEncoding];
[data writetoFile:[self dataFilePath]
atomically:YES];
}
我在代码行中插入了“ initForWritingWithMutableData:data”,并被告知要替换为“ initRequiringSecureCoding:Bool”。这使Xcode消除了警告,但是用户设置和数据不再保存。我相信这是因为我曾经将NSMutableData分配给存档器,但不再这样做了。我在文档中发现以下内容可能会有所帮助,但我不知道如何实现:
(NSData *)archivedDataWithRootObject:(id)object
requiringSecureCoding:(BOOL)requiresSecureCoding
error:(NSError * _Nullable *)error;
当应用再次启动时,我将加载它们的设置并使用以下内容保存数据:
// Restore settings
Nsstring *filePath = [self dataFilePath];
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
NSData *data = [[NSMutableData alloc] initWithContentsOfFile:[self dataFilePath]];
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingFromData:data error:NULL];
//initForReadingWithData:data];
“ initForReadingWithData:data”也已被弃用,并被告知要使用“ initForReadingFromData:error:”方法代替它。我“认为”很好。
任何帮助或建议都将不胜感激。
更新:由于TheNextman的建议,存档器正在运行。这是当前代码:
...
persistence.field20 = [NSNumber numberWithBool:self.instructionShown];
// NSMutableData *data = [[NSMutableData alloc] init];
// NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initRequiringSecureCoding:false];
[archiver encodeObject:persistence forKey:kDataKey];
[archiver finishEncoding];
NSData* data = [archiver encodedData];
[data writetoFile:[self dataFilePath] atomically:YES];
// [archiver encodeObject:persistence
// forKey:kDataKey];
// [archiver finishEncoding];
// [data writetoFile:[self dataFilePath]
// atomically:YES];
}
但是要使其正常工作,我必须继续使用不推荐使用的未归档代码。
// Restore settings
Nsstring *filePath = [self dataFilePath];
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
NSData *data = [[NSMutableData alloc] initWithContentsOfFile:[self dataFilePath]];
// NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingFromData:data error:NULL];
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
不建议再次使用“ initForReadingWithData:data”,并被告知要使用“ initForReadingFromData:error:”。如果使用新代码,则可以编译并正常运行,但不会再次出现用户数据。
解决方法
我没有测试它,但我认为您需要encodedData属性。
如果编码尚未完成,则调用此属性将调用finishEncoding并使用编码后的数据填充此属性
它返回一个NSData
指针,您可以将其写入磁盘
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initRequiringSecureCoding:false];
[archiver encodeObject:persistence forKey:kDataKey];
NSData* data = [archiver encodedData];
[data writeToFile:[self dataFilePath] atomically:YES];
然后我像这样取消归档该对象:
NSKeyedUnarchiver* unarchiver = [[NSKeyedUnarchiver alloc] initForReadingFromData:data error:nil];
[unarchiver setRequiresSecureCoding:NO];
Persistance* p = [unarchiver decodeObjectForKey:kDataKey];
请注意,我们必须明确地告诉取消存档者我们不需要安全编码(如为存档者指定的那样)。
如果您查看文档(实际上,例如上面的initForReadingFromData:error:
函数),则许多函数都带有可选的“错误”参数。
您可以传入NSError
指针,如果没有得到预期的结果,则检查其中包含的指针。例如:
NSKeyedUnarchiver* unarchiver = [[NSKeyedUnarchiver alloc] initForReadingFromData:data error:nil];
//[unarchiver setRequiresSecureCoding:NO]
NSError* err = nil;
Persistance* p = [unarchiver decodeTopLevelObjectOfClass:[Persistance class] forKey:kDataKey error:&err];
NSLog(@"%@ %@",p,err);
在这种情况下,您会看到问题所在:
(空)错误域= NSCocoaErrorDomain代码= 4864“此解码器将仅解码采用NSSecureCoding的类。“持久性”类不采用它。 UserInfo = {NSDebugDescription =此解码器将仅解码采用NSSecureCoding的类。 “持久性”类没有采用它。}