NSKeyedArchiver不推荐使用的方法问题

问题描述

仅提供一些背景信息。几年前,我失去了说话的能力,并且学会了如何专门编写代码以自己为语音应用创建良好的文本。令人惊讶的是,许多其他人发现它很有用。苹果每周报告约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的类。 “持久性”类没有采用它。}