ios - 如何将 NSKeyedUnarchiver unarchiveObjectWithData 更新为 NSKeyedUnarchiver unarchivedObjectOfClass :[fromData:error:

标签 ios objective-c nscoder nsarchiving

我的应用目前使用这个已弃用的函数:

id unarchivedObject=[NSKeyedUnarchiver unarchiveObjectWithData:codedData];
if([unarchivedObject isKindOfClass:[NSDictionary class]]){
    // currently returns TRUE when reading existing user data.
} 

为了更新,我已经转换成这样:

id unarchivedObject=[NSKeyedUnarchiver unarchivedObjectOfClass:[NSDictionary class] fromData:codedData error:nil];
if([unarchivedObject isKindOfClass:[NSDictionary class]]){
    // currently returns FALSE when reading existing user data.
}

数据最初是这样编码的:

-(void)encodeWithCoder:(NSCoder*)encoder{
    [encoder encodeObject:text forKey:@"text"];
}
-(instancetype)initWithCoder:(NSCoder*)decoder{
    if(self=[super init]){
        text=[decoder decodeObjectForKey:@"text"];
}

使用较新的代码可能导致 IF 语句返回 FALSE 的原因是什么?

请注意,我主要关心的是读取在弃用存档功能之前存储的现有数据。简单地更改为较新的功能并不能解决问题。

最佳答案

有趣的问题!我一直支持 iOS 10.0,所以在看到这个之前我没有遇到过这样的问题。我修修补补了一个小时,成功找到了问题。

What could be causing the IF statement to return FALSE using the newer code?

那是因为你的unarchivedObject对象是 nil!

如果使用参数error在新方法中,您会看到如下错误:

Error Domain=NSCocoaErrorDomain Code=4864 "This decoder will only decode classes that adopt NSSecureCoding. Class 'QTPerson' does not adopt it." UserInfo={NSDebugDescription=This decoder will only decode classes that adopt NSSecureCoding. Class 'QTPerson' does not adopt it.

但是我们如何得到这个 unarchivedObject 的正确值呢?而不是零?这需要几个步骤。

首先,让你的模型/类符合 <NSCoding, NSSecureCoding>

例子: QTPerson.h

#import <Foundation/Foundation.h>

@class QTPerson;

NS_ASSUME_NONNULL_BEGIN

#pragma mark - Object interfaces

@interface QTPerson : NSObject <NSCoding, NSSecureCoding>
@property (nonatomic, copy) NSString *text;
@end

NS_ASSUME_NONNULL_END

然后实现协议(protocol)方法:

QTPerson.m

#import "QTPerson.h"

@implementation QTPerson

+ (BOOL)supportsSecureCoding {
    return YES;
}

- (void)encodeWithCoder:(NSCoder *)coder {
    [coder encodeObject:_text forKey:@"text"];
}

- (instancetype)initWithCoder:(NSCoder *)coder {
    self = [super init];
    if (self) {
        _text = [coder decodeObjectOfClass:[NSString class] forKey:@"text"];
    }
    return self;
}

@end

然后在归档对象时,您可能希望传递 YES到参数 requiringSecureCoding ,像这样:

QTPerson *person = [[QTPerson alloc] init];
person.text = @"Glenn";

NSData *codedData1 = [NSKeyedArchiver archivedDataWithRootObject:person requiringSecureCoding:YES error:nil];
[[NSUserDefaults standardUserDefaults] setValue:codedData1 forKey:@"boom"];

最后,在取消存档时,只需按照正确的方式执行操作,如下所示:

NSData *codedData = [[NSUserDefaults standardUserDefaults] dataForKey:@"boom"];

NSError *er;
id unarchivedObject=[NSKeyedUnarchiver unarchivedObjectOfClass:[QTPerson class] fromData:codedData error:&er];

if([unarchivedObject isKindOfClass:[QTPerson class]]){
    NSLog(@"TRUE!");
} else {
    NSLog(@"FALSE!");
}

瞧!你会得到非空对象 unarchivedObject ,因此您要查找的是 TRUE/YES 值!

关于ios - 如何将 NSKeyedUnarchiver unarchiveObjectWithData 更新为 NSKeyedUnarchiver unarchivedObjectOfClass :[fromData:error:,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58043107/

相关文章:

ios - 在 iOS 7.1 应用程序 xcode 5.1 中获取数字百分比时遇到问题

iphone - 保存 UIView 以供下次启动(不是作为图像)

ios - AWS Cognito 使用 Firebase 电子邮件和密码 IOS 对用户进行身份验证

ios - 我正在构建一个 iOS 应用程序,只是选择使用 AWS iOS SDK 而不是 BaaS 来构建后端。我刚刚为自己创造了哪些额外的工作?

ios - UITableView + 核心数据

iOS:缓存下载的 RSS 消息的最佳方法

ios - 如何将 NSCoder 与版本化类一起使用

iphone - 将图像从 URL 加载到 UIImageview 需要时间

ios - PresentViewController 一个带有 UINavigationController 的非全屏 UIViewController

ios - 在两个 View 之间水平滑动